遇到了JS的變量聲明提升,英文名為Hosting,具體來(lái)講是指JS在對(duì)當(dāng)前作用域中的聲明代碼孩擂,會(huì)將其提升至當(dāng)前作用域的最頂端。本文通過(guò)幾個(gè)示例來(lái)詳細(xì)理解一下:
示例一
- 正常預(yù)期的輸出
var myvar = 'my value';
(function() {
alert(myvar);
})();
這種情況下箱熬,在瀏覽器中執(zhí)行类垦,會(huì)看到 my value
的提示框。
- 異常不符合預(yù)期的輸出
var myvar = 'my value';
(function() {
alert(myvar);
var myvar = 'local value';
})();
這時(shí)城须,我們確得到的輸出資料是 undefined
蚤认。并不是全局的 myvar,這就是因?yàn)樵趂unction的作用域內(nèi)糕伐,將變量myvar
的聲明提升至 alert
的上方砰琢,等同于下面的代碼:
var myvar = 'my value';
(function() {
var myvar;
alert(myvar);
myvar = 'local value';
})();
示例二
(function (){
newFuntion();
var newFuntion = function(){
alert("hello word");
}
})();
這段代碼將不會(huì)有任何輸出,但會(huì)得到一個(gè)錯(cuò)誤信息良瞧,Uncaught TypeError: newFuntion is not a function
陪汽。可以看出褥蚯,其也會(huì)對(duì)函數(shù)的變量聲明也會(huì)進(jìn)行提升挚冤,等同于這段代碼:
(function (){
var newFuntion;
newFuntion();
newFuntion = function(){
alert("hello word");
}
})();
但是,這樣調(diào)用就不會(huì)出錯(cuò):
(function (){
newFuntion();
function newFuntion(){
alert("hello word");
}
})();
這是函數(shù)聲明的寫法赞庶,會(huì)優(yōu)先在當(dāng)前作用域進(jìn)行函數(shù)的注冊(cè)你辣,所以調(diào)用的時(shí)候,函數(shù)已經(jīng)存在尘执,沒(méi)有問(wèn)題舍哄。
示例三
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
這個(gè)示例的輸出,給我們的結(jié)果是個(gè)"1"的彈出框誊锭,很困惑了有木有表悬?對(duì)代碼改動(dòng)一下,
var a = 1;
function b() {
alert(a);
a = 10;
return;
function a() {}
}
b();
得到的a 是function a(){}
丧靡。得到的結(jié)果是其對(duì)函數(shù)的聲明蟆沫。需要注意的是,這里在function b下面的a因?yàn)楹瘮?shù)聲明的問(wèn)題温治,已經(jīng)變?yōu)榱艘粋€(gè)局部變量饭庞,所以不會(huì)影響全局變量a,所以之前代碼的結(jié)果輸出為1熬荆,也就很容易理解了舟山。
總結(jié)
變量聲明的時(shí)候,變量賦值并沒(méi)有被提升,只是聲明被提升了累盗。但是寒矿,同時(shí)要注意函數(shù)聲明與函數(shù)表達(dá)式的區(qū)別: 函數(shù)聲明會(huì)在當(dāng)前作用域優(yōu)先進(jìn)行注冊(cè),會(huì)產(chǎn)生覆蓋的效果若债,而函數(shù)表達(dá)式則是按代碼順序進(jìn)行執(zhí)行 符相。所以下面這段也就容易理解了:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // 變量指向函數(shù)表達(dá)式
alert("this won't run!");
}
function bar() { // 函數(shù)聲明 函數(shù)名為bar
alert("this will run!");
}
}
test();