函数声明和变量声明都会被提升。但一个微妙的细节(可以 在拥有多个“重复的”声明的代码中出现)是,函数会首先被提升,然后才是变量。
考虑这段代码:
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
1
被打印了,而不是 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 );
}
虽然这一切听起来不过是一些有趣的学院派细节,但是它强调了一个事实:在同一个作用域内的重复定义是一个十分差劲儿的主意,而且经常会导致令人困惑的结果。
在普通的块儿内部出现的函数声明一般会被提升至外围的作用域,而不是像这段代码暗示的那样有条件地被定义:
foo(); // "b"
var a = true;
if (a) {
function foo() { console.log( "a" ); }
}
else {
function foo() { console.log( "b" ); }
}
然而,重要的是要注意这种行为是不可靠的,而且是未来版本的 JavaScript 将要改变的对象,所以避免在块儿中声明函数可能是最好的做法。