淺析JavaScript中的提升

JavaScript代碼在執(zhí)行時并不完全是由上到下一行一行執(zhí)行的,由此產(chǎn)生了一個提升的問題。

什么是提升

可以簡單理解為:聲明(變量和函數(shù))都會被“移動”到各自作用域的最頂端,這個過程被稱為提升。

具體例子看提升

下面兩個例子a會log什么出來呢?

a = 233;
var a;
console.log(a)
console.log(a);
var a = 233;

“看起來”第一個例子應(yīng)該log出undefined,第二個例子變量a在使用前沒有先進行聲明,因此會拋出ReferenceError異常。但實際上,第一個例子a輸出233,第二個例子a輸出undefined。

為什么?

在知道為什么之前有必要了解:JavaScript雖然是解釋型語言,但在解釋JavaScript代碼之前首先對其進行編譯的。編譯階段中的一部分工作就是找到所有的聲明,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來。

變量和函數(shù)在內(nèi)的所有聲明都會在任何代碼被執(zhí)行前首先被處理。

var a = 233;

上面的聲明看起來是一個聲明,而對于JavaScript而言實際上這是兩個聲明:var a;和a = 233;。第一個定義聲明是在編譯階段進行的。第二個賦值聲明會被留在原地等待執(zhí)行階段。

看回前面兩個例子,第一個例子的代碼會被這樣處理:

var a;
a = 233;
console.log(a);

第二個例子:

var a;
console.log(a);
a = 233;

注意:只有聲明本身會被提升,而賦值或其他運行邏輯會留在原地 。

函數(shù)聲明與函數(shù)表達式

第一個例子:

foo();
function foo() {
  console.log(a); // undefined
  var a = 233;
}

函數(shù)foo可以正常執(zhí)行。
第二個例子:

foo(); // TypeError
var foo = function bar() {
  // ...
}

報錯:Uncaught TypeError: foo is not a function

由此可以看到:函數(shù)聲明會被提升,但是函數(shù)表達式卻不會被提升。
第三個例子:

foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
  // ...
};

這段代碼經(jīng)過提升后,可以理解為以下形式:

var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function() {
  var bar = ...self...
  // ...
};

由此可見:具名的函數(shù)表達式,名稱標(biāo)識符在賦值之前也無法在所在作用域中使用。

函數(shù)優(yōu)先

既然函數(shù)聲明和變量聲明都會被提升,那么問題來了,重復(fù)聲明的代碼中的優(yōu)先級是怎樣的,是函數(shù)聲明被提升還是變量聲明被提升?
繼續(xù)驗證:

foo(); // 1
var foo;
function foo() {
  console.log( 1 );
}
foo = function() {
  console.log( 2 );
}

var foo盡管出現(xiàn)在 function foo()...的聲明之前,但它是重復(fù)的聲明而被忽略,因為函數(shù)聲明會被提升到普通變量之前。可以得知:函數(shù)聲明提升的優(yōu)先權(quán)大于普通變量聲明。

盡管重復(fù)的var聲明會被忽略掉,但出現(xiàn)在后面的函數(shù)聲明還是可以覆蓋前面的

foo(); // 3
function foo() {
  console.log( 1 );
}
var foo = function() {
  console.log( 2 );
};
function foo() {
  console.log( 3 );
}

ES6中的變量聲明

ES6新增了let、const聲明,它們會存在一個暫時性死區(qū)(TDZ),表現(xiàn)出的情況會有所不同,具體可以參考:let, const

總結(jié)

  • var變量聲明和函數(shù)聲明存在提升
  • 函數(shù)表達式不會被提升
  • 函數(shù)聲明提升的優(yōu)先權(quán)大于普通變量聲明
  • let, const由于存在暫時性死區(qū),表現(xiàn)出的情況和var聲明有所不同
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容