提升
a = 2;
var a;
console.log( a );
相當(dāng)于
var a;
a = 2;
console.log( a );//2
console.log( a );
var a = 2;
相當(dāng)于
var a;
console.log( a );
a = 2;
這個(gè)過程就好像變量和函數(shù)聲明從它們?cè)诖a中出現(xiàn)的位置被“移動(dòng)”到了最上面膀斋。這個(gè)過程就叫做提升淡溯。
只有聲明本身會(huì)被提升兵琳,而賦值或其他運(yùn)行邏輯會(huì)留在原地。如果提升改變了代碼執(zhí)行的順序硕噩,會(huì)造成非常嚴(yán)重的破壞假残。
函數(shù)聲明會(huì)被提升,但是函數(shù)表達(dá)式卻不會(huì)被提升炉擅。如:
foo();// 不是ReferenceError, 而是TypeError!
var foo=function bar() {
console.log(a); // undefined
var a = 2;
}
以上程序中的變量標(biāo)識(shí)符foo()被提升并分配給所在作用域(在這里是全局作用域)辉懒,因此foo()不會(huì)導(dǎo)致ReferenceError。但是foo此時(shí)并沒有賦值(如果它是一個(gè)函數(shù)聲明而不是函數(shù)表達(dá)式谍失,那么就會(huì)賦值)眶俩。foo()由于對(duì)undefined值進(jìn)行函數(shù)調(diào)用而導(dǎo)致非法操作,因此拋出TypeError異常快鱼。
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
// ...
};
改為:
var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function() {
var bar = ...self...
// ...
}
函數(shù)優(yōu)先
函數(shù)聲明和變量聲明都會(huì)被提升颠印。但是一個(gè)值得注意的細(xì)節(jié)(這個(gè)細(xì)節(jié)可以出現(xiàn)在有多個(gè)“重復(fù)”聲明的代碼中)是函數(shù)會(huì)首先被提升,然后才是變量抹竹。
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};
這個(gè)代碼片段會(huì)被引擎理解為:
function foo() {
console.log( 1 );
}
foo(); // 1
foo = function() {
console.log( 2 );
};
注意嗽仪,var foo盡管出現(xiàn)在function foo()...的聲明之前,但它是重復(fù)的聲明(因此被忽略了)柒莉,因?yàn)楹瘮?shù)聲明會(huì)被提升到普通變量之前。
盡管重復(fù)的var聲明會(huì)被忽略掉沽翔,但出現(xiàn)在后面的函數(shù)聲明還是可以覆蓋前面的:
foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}