前言:
JS中在聲明函數(shù)與變量的時候是存在變量提升的問題,一不注意符糊,有的時候會導(dǎo)致一些bug,本文主要就是針對JS中的提升問題蜜笤。JS中的提升濒蒋,分為變量提升與函數(shù)提升,并且函數(shù)提升是優(yōu)先于變量提升的把兔。當(dāng)然此文討論的內(nèi)容不包括ES6沪伙。
提升的概念
其實針對這個概念,私以為可以簡單的理解為JS解析器將函數(shù)的聲明與變量的聲明提升到所在作用域的頂部县好,以方便使用围橡。注意,只是將聲明提前缕贡,賦值并沒有提前翁授。
實例說明
console.log(a); // undefined
console.log(b); // function b() {alert(98);}
b(); // 98
function b() {
console.log(98);
}
var a = 97;
上面的例子其實就相當(dāng)于是:
function b() {
alert(98);
}
var a;
b(); // 98
console.log(a); // undefined
console.log(b); // function b() {alert(98);}
a = 97;
塊中的提升
在JS的塊中聲明函數(shù)的時候拣播,出現(xiàn)的了比較有趣的現(xiàn)象:
console.log(a); // undefined
console.log(b); // undefined
console.log(c); // undefined
console.log(d); // undefined
// b() //不注釋掉會報錯
if (true) {
var a = 97;
b(); // 98
function b() {
console.log(98);
}
} else {
var c = 99;
function d() {
console.log(100);
}
}
console.log(a, b, c, d);
// a = 97
// b = function b() {console.log(98)}
// c = undefined
// d = undefined
現(xiàn)在這個情況就有點意思了:
因為JS是不存在塊級作用域的,所以變量 a 和 c 打印出來 undefined 是很好理解的收擦,但是 b 和 d 是什么情況呢贮配?
為什么也是 undefined 呢?這到底是提升了還是沒提升呢塞赂?
經(jīng)過查閱資料泪勒,我認(rèn)為這塊是瀏覽器的一種容錯機(jī)制的結(jié)果(未針對所有瀏覽器的不同版本進(jìn)行測試,如果有錯誤宴猾,希望留言斧正圆存,謝謝)。因為嚴(yán)格來說仇哆,在塊中聲明函數(shù)屬于無效語法沦辙,JS引擎會嘗試修正錯誤,將其轉(zhuǎn)化為合理的狀態(tài)(這點在《JavaScript高級程序設(shè)計 第三版》176頁也是一筆帶過)讹剔。
我認(rèn)為油讯,瀏覽器嘗試修正的時候是將函數(shù)申明轉(zhuǎn)化為函數(shù)表達(dá)式,并放在塊的最頂部延欠。所以函數(shù)的變量名進(jìn)行了提升撞羽,而函數(shù)體其實只是一種折中的提升
// 上邊代碼相當(dāng)于是這樣
var a;
var b;
var c;
var d;
if (true) {
b = function b() {
console.log(98);
};
a = 97;
b(); // 98
} else {
d = function () {
console.log(100);
}
c = 99;
}
// 受限于水平,如有錯誤衫冻,歡迎留言斧正,謝謝
針對這種情況谒出,強(qiáng)烈不建議在塊中出現(xiàn)函數(shù)聲明隅俘,建議改為函數(shù)表達(dá)式。
總結(jié)
只要記住這個關(guān)鍵的點笤喳,其他的類似這樣題目都會迎刃而解为居,當(dāng)然搞懂這個不是為了做題,而是為了避免一些工作中的bug杀狡,所以推薦以后在寫代碼的時候蒙畴,最好按照如下的格式去書寫
function fun() {
// 聲明各種變量
// 聲明函數(shù)
// 其他語句
}
參考鏈接:
JavaScript Scoping and Hoisting
Firefox doesn’t hoist function declarations in blocks
本文為作者原創(chuàng),版權(quán)所有呜象,轉(zhuǎn)載請注明出處膳凝。