JS执行顺序-函数声明提升、匿名函数、函数表达式

JS 是按照代码块进行 编译、执行 的。


script标签区分代码块

1
2
3
4
5
6
<script>
alert('代码块一');
</script>
<script>
alert('代码块二');
</script>

关于函数(声明式函数、赋值型(函数表达式)函数、匿名函数、自执行函数)

函数提升

声明函数与赋值函数的区别在于: 在 JS 的预编译期间,声明式函数会被先提取出来,然后才按照顺序执行 JS代码。

1
2
3
4
5
6
7
8
9
A();  // 'A '
function A() {
console.log('A');
}

B(); // error, B is not a function
var B = function() {
console.log('B');
}

匿名函数(没有名字的函数)

1
function() {} // 匿名函数

自执行函数

1
2
3
4
5
6
7
8
9
10
11
12
13
(function() {
console.log(3);
})();

// 带参数
(function(num){
console.log(num);
})(3); // 3

// 没有括号会报错 如下
function() {
console.log(3);
}();

原因如下:

  • function {}()其实这是一个函数声明。
  • JS运行的时候,会对函数声明进行预编译,然后在执行其他语句。
  • 也就是说function(){}先被预编译了。然后JS看见了()。JS一脸懵逼,这不得报错吗。
  • 而匿名函数实际上是一个语句,正常执行。

自执行函数的标识也可以是

1
2
!function(){}()      (function(){})()    
~function(){}() void function(){}()

预编译期和执行期

JS的解析分为两个阶段:预编译 和 执行期。

  • 预编译期间:对本代码块中的所有声明变量和函数进行处理(类似于C语言的编译) ,但需要注意,1.此时处理函数的只是 声明式函数2.变量也只是进行了声明但是没有进行初始化和赋值
  • 编译期间:从上到下编译代码块。

函数声明提前且后来居上覆盖

1
2
3
4
5
6
7
8
9
getName(); // 6
function getName() { alert (5);}
var getName = function () { alert (4);};
function getName() { alert (6);}

---
var getName = function () { alert (4);};
function getName() { alert (6);}
getName(); // 4 函数声明都被提升了,表达式会覆盖掉

练习题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Foo() {
// 全局变量
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);} // 函数提升 JavaScript永远不会有函数重载

//请写出以下输出结果:
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1 覆盖了函数表达式
getName(); // 1
new Foo.getName(); // 2 new (Foo.getName)()
new Foo().getName(); // 3 (new Foo()).getName();

ES6之前,JS没有变量作用域。只有 函数作用域 和 全局作用域。

1
2
3
4
5
6
7
8
9
{
var a = 3;
}
console.log(a); // 3
---
{
let a = 3;
}
console.log(a); // error
本文结束感谢您的阅读

本文标题:JS执行顺序-函数声明提升、匿名函数、函数表达式

文章作者:陈宇(cosyer)

发布时间:2018年06月13日 - 17:06

最后更新:2018年12月15日 - 13:12

原始链接:http://mydearest.cn/executionOrder.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!