提升
對於「提升」,其實它不是一個原本特有的名詞,
而是用來了解在 JavaScript 當中如何運行的,
主要是由於 JavaScript 當中執行階段的關係,而導致這個情況。
變數提升
不過一般而言,這個模式很容易令人誤解,可能會因為變數宣告放在比較後面,
然後以為藉由變數提升,導致我們可能以為只是單純將變數移動至上方做使用。
舉個例子來說:
1 | var name = "Arance"; |
對於我們理解程式碼由上而下做解析,的確這樣名字會印出 Arance。
但如果是這樣的例子:
1 | console.log(name); |
我們可能會覺得,今天由上而下的概念,這樣名字還沒被宣告就拿來用,
應該會有錯吧(?)但這樣名字卻會顯示 undefined。
不會噴錯誤訊息???????
對!在 JavaScript 裡面的運行的確只會得到 undefined。
這是因為 JavaScript 擁有兩階段執行。
兩階段執行
什麼是兩階段執行?
對於 JavaScript 執行程式,有兩個期間:
建立期 - 在建立期時,主要會做註冊名稱(建立變數)+初始化。
執行期 - 在執行期時,賦予值或是執行函數。
例子 1:
這樣講可能有點抽象,像上面的例子而言:
1 | var name = "Arance"; |
在建立期時:
第一條,主要將 name 建立這個變數,並對它做初始化,將 name 指定為 undefined。
而對於第二條,console.log(name)不會做任何事。
在執行期時:
第一條會將 name 指定為 Arance,就是所謂的賦予值。
第二條,console.log(name)就會執行函數,而將它印出來。
例子 2:
1 | console.log(name); |
在建立期時:
第一條,console.log(name)不會做任何事。
第二條,主要將 name 建立這個變數,並對它做初始化,將 name 指定為 undefined。
在執行期時:
第一條,console.log(name)就會執行函數,而將它印出來,所以會得到 undefined。
第二條會將 name 指定為 Arance,就是所謂的賦予值。
所以才導致,這樣印出來是 undefined。
針對 var 而言的變數提升,而很多人認為 let 不會做變數提升,
但其實會,只不過我們在宣告 let 前就使用的話,會出現錯誤。
例如:
1 | console.log(name); |
在建立期時:
第一條,console.log(name)不會做任何事。
第二條,主要將 name 建立這個變數,但不會對它做初始化。
在執行期時:
第一條,console.log(name)就會執行函數,但由於沒有定義,所以會直接跳出錯誤訊息。
主要因為沒有初始化,導致錯誤訊息,那是因為使用 let 宣告變數,
會存在於暫時死區(Temporal Dead Zone,簡稱 TDZ),
而對於 let 以及 const 宣告變數都會存在於 TDZ 內。
暫時死區
暫時死區的好處就是可以避免我們在對變數宣告前就做使用,會進入的一區域,
這樣只要在使用前沒宣告的話,在使用當下就會直接告訴我們錯誤訊息。
總結
雖然變數提升,雖然可以讓我們在宣告之前就可以使用變數,
但同樣的也會有所缺點是,或許這個會使用到其他人所定義的變數,
那或許根本不是我們想要的變數。