提升
a = 2;
var a;
console.log( a );
相当于
var a;
a = 2;
console.log( a );//2
console.log( a );
var a = 2;
相当于
var a;
console.log( a );
a = 2;
这个过程就好像变量和函数声明从它们在代码中出现的位置被“移动”到了最上面。这个过程就叫做提升。
只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码执行的顺序,会造成非常严重的破坏。
函数声明会被提升,但是函数表达式却不会被提升。如:
foo();// 不是ReferenceError, 而是TypeError!
var foo=function bar() {
console.log(a); // undefined
var a = 2;
}
以上程序中的变量标识符foo()被提升并分配给所在作用域(在这里是全局作用域),因此foo()不会导致ReferenceError。但是foo此时并没有赋值(如果它是一个函数声明而不是函数表达式,那么就会赋值)。foo()由于对undefined值进行函数调用而导致非法操作,因此抛出TypeError异常。
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
// ...
};
改为:
var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function() {
var bar = ...self...
// ...
}
函数优先
函数声明和变量声明都会被提升。但是一个值得注意的细节(这个细节可以出现在有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量。
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 );
}
但愿人长久,千里共婵娟