详解JavaScript中的函数声明和函数表达式
作者:libuchao 时间:2023-04-26 01:56:07
JavaScript 中需要创建函数的话,有两种方法:函数声明、函数表达式,各自写法如下:
// 方法一:函数声明
function foo() {}
// 方法二:函数表达式
var foo = function () {};
另外还有一种自执行函数表达式,主要用于创建一个新的作用域,在此作用域内声明的变量不会和其它作用域内的变量冲突或混淆,大多是以匿名函数方式存在,且立即自动执行:
(function () {
// var x = ...
})();
此种自执行函数表达式归类于以上两种方法的第二种,也算是函数表达式。
方法一和方法二都创建了一个函数,且命名为 foo,但是二者还是有区别的。JavaScript 解释器中存在一种变量声明被提升(hoisting)的机制,也就是说变量(函数)的声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。
例如以下代码段:
alert(foo); // function foo() {}
alert(bar); // undefined
function foo() {}
var bar = function bar_fn() {};
alert(foo); // function foo() {}
alert(bar); // function bar_fn() {}
输出结果分别是function foo() {}、undefined、function foo() {}和function bar_fn() {}。
可以看到 foo 的声明是写在 alert 之后,仍然可以被正确调用,因为 JavaScript 解释器会将其提升到 alert 前面,而以函数表达式创建的函数 bar 则不享受此待遇。
那么bar 究竟有没有被提升呢,其实用 var 声明的变量都会被提升,只不过是被先赋值为 undefined 罢了,所以第二个 alert 弹出了 undefined。
所以,JavaScript 引擎执行以上代码的顺序可能是这样的:
创建变量 foo 和 bar,并将它们都赋值为 undefined。
创建函数 foo 的函数体,并将其赋值给变量 foo。
执行前面的两个 alert。
创建函数 bar_fn,并将其赋值给 bar。
执行后面的两个 alert。
注:
严格地说,再 JavaScript 中创建函数的话,还有另外一种方法,称为“函数构造法”:
var foo = Function('alert("hi!");');
var foo = new Function('alert("hi!");'); // 等同于上面一行
此方法以一个字符串作为参数形成函数体。但是用这种方法,执行效率方面会打折扣,且似乎无法传递参数,所以少用为妙。
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Android自定义view系列之99.99%实现QQ侧滑删除效果实例代码详解
![](https://img.aspxhome.com/file/2023/3/100593_0s.png)
Mybatis 如何开启控制台打印sql语句
![](https://img.aspxhome.com/file/2023/5/99865_0s.jpg)
Android开发之ToggleButton实现开关效果示例
详解Asp.Net MVC的Bundle捆绑
![](https://img.aspxhome.com/file/2023/2/96322_0s.png)
Android之ImageSwitcher的实例详解
![](https://img.aspxhome.com/file/2023/9/137689_0s.png)
C#中析构函数、Dispose、Close方法的区别
VsCode配置java环境的详细图文教程
![](https://img.aspxhome.com/file/2023/8/132188_0s.jpg)
IDEA代码规范插件P3C+代码注释模板配置方法
![](https://img.aspxhome.com/file/2023/8/86838_0s.png)
java web实现分页查询实例方法
![](https://img.aspxhome.com/file/2023/9/72399_0s.png)
Spring Boot2.x如何自定义Endpoint
C#实现绘制鼠标的示例代码
![](https://img.aspxhome.com/file/2023/4/77234_0s.png)
Java使用pulsar-flink-connector读取pulsar catalog元数据代码剖析
java程序代码与文本对比实用工具简介
![](https://img.aspxhome.com/file/2023/9/77489_0s.png)
selenium.chrome写扩展拦截或转发请求功能
![](https://img.aspxhome.com/file/2023/0/111150_0s.gif)
Springboot如何利用拦截器拦截请求信息收集到日志详解
详解Android中的MVP架构分解和实现
![](https://img.aspxhome.com/file/2023/0/139080_0s.png)
Android 8.0系统中通知栏的适配详解
![](https://img.aspxhome.com/file/2023/4/139314_0s.png)
Java多线程synchronized同步方法详解
![](https://img.aspxhome.com/file/2023/6/81226_0s.png)
JavaWeb购物车项目开发实战指南
![](https://img.aspxhome.com/file/2023/8/129958_0s.jpg)
Java实现简单学生管理系统
![](https://img.aspxhome.com/file/2023/1/69901_0s.png)