声明与赋值谁在前
先看两个例子
例子1:
a = 2; var a; console.log( a ); // 2
例子2:
console.log( a ); // undefined var a = 2;
例子1:为什么结果不是 undefined 。
例子2:为什么结果不是 抛出 ReferenceError 异常。
那为什么会出现这个结果呢?
编译器再度来袭
为了弄清这个问题,再次需要了解编译器的内容。
引擎会在解释 JavaScript 代码之前首先对其进行编译。编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来。
因此,包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。
上面的两个例子就很好理解了。
以例子2为例:
console.log( a ); // undefined var a = 2; // 先编译,后执行 等价于 var a; console.log( a ); a = 2;
这个过程就好像变量和函数声明从它们在代码中出现的位置被移动
到了最上面。这个过程就叫作提升
。
注意:每个作用域都会进行提升操作。声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升。
函数优先
函数声明和变量声明都会被提升。(有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量
。
例子1:
foo(); // 1 var foo; function foo() { console.log( 1 ); } foo = function() { console.log( 2 ); };
这个代码会被引擎理解为:
function foo() { console.log( 1 ); } foo(); // 1 foo = function() { console.log( 2 ); };
注意:var foo
尽管出现在 function foo()
的声明之前,但它是重复声明的(被忽略掉了),函数声明会被提升到普通变量之前。
尽管重复的 var 声明会被忽略掉,但出现在后面的函数声明还是可以覆盖前面的。
例子:
foo(); // 3 function foo() { console.log( 1 ); } var foo = function() { console.log( 2 ); }; function foo() { console.log( 3 ); }