关于javascript里的声明提前(hoisting)

“声明提前”是在javascript引擎的“预编译”时进行的,也就是在代码开始运行之前。

在函数里声明的所有变量(但不涉及赋值),都会被“提前”至函数体的顶部。在函数体内,局部变量的优先级高于同名的全局变量,如果在函数体内声明一个局部变量或者函数参数中带有的变量和全局变量同名,那么全局变量将会被局部变量覆盖。而给一个没有被声明的变量赋值,在非严谨模式下,等同于在全局范围创建了一个同名属性。

在脚本里,所有的函数包括嵌套的函数,都会在当前的上下文中其他代码之前声明。函数定义语句中的函数会被显式地“提前”(包括函数名和函数体),在脚本和函数内部都是可见的,因此可以被提前调用。而使用var的话(函数定义表达式),只有变量会被提前,变量的定义还在原来的位置。

反面教材1

1
2
3
4
5
6
7
8
9
10
(function(a){
console.log(a); // 输出 function a(){}
var a = 10;
function a(){};
})(100);
(function(a){
console.log(a); // 输出 100
var a = 10;
})(100);

反面教材2

1
2
3
4
5
console.log(a); // 输出 functiong a(){}
functiong a(){};
console.log(a); // 输出 undefined
var a = funciton(){};

反面教材3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function(){
a = 10;
console.log(a); // 输出 10
console.log(window.a); // 输出 undefined
var a = 20;
console.log(a); // 输出 20
})();
// 等于下面的
var a;
(function(){
var a;
a = 10;
console.log(a); // 输出 10
console.log(window.a); // 输出 undefined
a = 20;
console.log(a); // 输出 20
})();