JavaScript 變數提升

提升

對於「提升」,其實它不是一個原本特有的名詞,

而是用來了解在 JavaScript 當中如何運行的,

主要是由於 JavaScript 當中執行階段的關係,而導致這個情況。

變數提升

不過一般而言,這個模式很容易令人誤解,可能會因為變數宣告放在比較後面,

然後以為藉由變數提升,導致我們可能以為只是單純將變數移動至上方做使用。

舉個例子來說:

1
2
var name = "Arance";
console.log(name);

對於我們理解程式碼由上而下做解析,的確這樣名字會印出 Arance。

但如果是這樣的例子:

1
2
console.log(name);
var name = "Arance";

我們可能會覺得,今天由上而下的概念,這樣名字還沒被宣告就拿來用,

應該會有錯吧(?)但這樣名字卻會顯示 undefined。

不會噴錯誤訊息???????

對!在 JavaScript 裡面的運行的確只會得到 undefined。

這是因為 JavaScript 擁有兩階段執行。

兩階段執行

什麼是兩階段執行?

對於 JavaScript 執行程式,有兩個期間:

  1. 建立期 - 在建立期時,主要會做註冊名稱(建立變數)+初始化。

  2. 執行期 - 在執行期時,賦予值或是執行函數。

例子 1:

這樣講可能有點抽象,像上面的例子而言:

1
2
var name = "Arance";
console.log(name);

在建立期時:

第一條,主要將 name 建立這個變數,並對它做初始化,將 name 指定為 undefined。
而對於第二條,console.log(name)不會做任何事。

在執行期時:

第一條會將 name 指定為 Arance,就是所謂的賦予值。

第二條,console.log(name)就會執行函數,而將它印出來。

例子 2:

1
2
console.log(name);
var name = "Arance";

在建立期時:

第一條,console.log(name)不會做任何事。

第二條,主要將 name 建立這個變數,並對它做初始化,將 name 指定為 undefined。

在執行期時:

第一條,console.log(name)就會執行函數,而將它印出來,所以會得到 undefined。

第二條會將 name 指定為 Arance,就是所謂的賦予值。

所以才導致,這樣印出來是 undefined。

針對 var 而言的變數提升,而很多人認為 let 不會做變數提升,

但其實會,只不過我們在宣告 let 前就使用的話,會出現錯誤。

例如:

1
2
console.log(name);
let name = "Arance";

在建立期時:

第一條,console.log(name)不會做任何事。

第二條,主要將 name 建立這個變數,但不會對它做初始化。

在執行期時:

第一條,console.log(name)就會執行函數,但由於沒有定義,所以會直接跳出錯誤訊息。

主要因為沒有初始化,導致錯誤訊息,那是因為使用 let 宣告變數,

會存在於暫時死區(Temporal Dead Zone,簡稱 TDZ),

而對於 let 以及 const 宣告變數都會存在於 TDZ 內。

暫時死區

暫時死區的好處就是可以避免我們在對變數宣告前就做使用,會進入的一區域,

這樣只要在使用前沒宣告的話,在使用當下就會直接告訴我們錯誤訊息。

總結

雖然變數提升,雖然可以讓我們在宣告之前就可以使用變數,

但同樣的也會有所缺點是,或許這個會使用到其他人所定義的變數,

那或許根本不是我們想要的變數。


參考資料:

MDN - Hosting