做前端的同學肯定對變量提升和函數提升不陌生,但實際應用中依然會有出錯的情況,前端時間組內成員review代碼發現很多小d在這個問題上沒有徹底弄清楚,本篇博文詳細做一次刨析。
變量提升
首先看下這個問題:輸出結果是什麼?
var x =20;
function s()
{
console.log(x);
var x = 10;
console.log(x);return x;
};
s();
經測試輸出結果應該;
undefined
10
爲什麼第一個console.log(x)會是undefined,其原因就是由於在函數s()內部發生了變量提升,雖然外部已經聲名定義了x=20,但當調用函數s()時內部變量x會首先覆蓋外部全局變量x,同時將x局部變量提升,在函數第一句執行console.log(x)時因爲此時x變量聲明得到提升但並未賦值,所以報的是undefined,等運行到第二句var x = 10;後局部變量纔有值。
驗證下如果不聲明 x
函數提升
函數作爲js中的一等公民同樣也存在函數提升的問題,看一下問題輸出什麼結果?
y();
function y() {
alert(2);
};
x();
var x = function() {
alert(1);
};
結果如下:
函數y如果一變量方式定義當變量提升時是無法調用的,如果直接function定義則會以函數提升的方式被調用。這也間接回答兩種定義函數的區別,所以推薦方式就是定義變量(函數表達式)的方式。
猜下下面代碼執行的結果:
y();
(function(){
var x = function(){alert(0)}
})();
(function(){
alert(2);
}());
!function(){
alert(3);
}();
function y() {
alert(2);
};
x();
var x = function() {
alert(1);
};
同樣箭頭函數也屬於第二種(函數表達式定義)方式,必須先定義後使用。
綜結
js程序的執行分爲函數和變量的聲明階段 與 執行階段 兩個階段
函數和變量的聲明階段 會先於 執行階段 進行。
普通函數就是在聲明階段創建的。
箭頭函數屬於匿名函數,匿名函數是要通過賦值語句賦值給變量,這個賦值的過程是在代碼執行階段進行的,不是在聲明階段,所以沒有函數聲明提升的特性。