对于var a = 3
我们一般认为这是一个声明,但实际上JavaScript引擎并不这么认为。它将var a
和a = 2
当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。
这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。 考虑如下代码段:
1 | a = 3; |
可能你会觉得上述代码将输出undefined
,但其实际上它能够如愿的输出3。因为上述代码在经过JavaScript引擎编译之后,变成了这样:
1 | var a; |
这种对变量的声明被拉到其作用域的最顶端的过程就是提升。
再如有如下代码段:
1 | console.log(a); |
上述代码将输出undefined
,而非ReferenceError
异常,如上所述,在经过JavaScript引擎编译之后,var a
被提升到了作用于顶部:
1 | var a; |
所以对a的RHS查询并不会失败,只不过a为undefined
罢了。
函数的声明也可以被提升,比如:
1 | foo(); // 3 |
实际上为:
1 | function foo() { |
函数声明的提升需要注意一点:
函数优先原则:函数声明和变量声明都会被提升。但函数声明将先被提升:
1 | foo(); // 4 |
经过JavaScript引擎编译之后,代码变成:
1 | function foo() { |
其中var foo
这个重复的声明已经被略去。