JavaScript中的提升

对于var a = 3我们一般认为这是一个声明,但实际上JavaScript引擎并不这么认为。它将var aa = 2当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。

这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升 考虑如下代码段:

1
2
3
a = 3;
var a;
console.log(a);

可能你会觉得上述代码将输出undefined,但其实际上它能够如愿的输出3。因为上述代码在经过JavaScript引擎编译之后,变成了这样:

1
2
3
var a;
a = 3;
console.log(a);

这种对变量的声明被拉到其作用域的最顶端的过程就是提升

再如有如下代码段:

1
2
console.log(a);
var a = 3;

上述代码将输出undefined,而非ReferenceError异常,如上所述,在经过JavaScript引擎编译之后,var a被提升到了作用于顶部:

1
2
3
var a;
console.log(a);
a = 3;

所以对a的RHS查询并不会失败,只不过a为undefined罢了。

函数的声明也可以被提升,比如:

1
2
3
4
5
foo(); // 3
function foo() {
var a = 3;
console.log(a);
}

实际上为:

1
2
3
4
5
function foo() {
var a = 3;
console.log(a);
}
foo(); // 3

函数声明的提升需要注意一点:

函数优先原则:函数声明和变量声明都会被提升。但函数声明将先被提升:

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

经过JavaScript引擎编译之后,代码变成:

1
2
3
4
5
6
7
8
9
function foo() {
var a = 4;
console.log(a);
}
foo();
foo = function() {
var a = 3;
console.log(a);
}

其中var foo这个重复的声明已经被略去。

《你不知道的JavaScript上卷》读书笔记

请作者喝瓶肥宅水🥤

0