[JS] 提昇(Hoisting)機制
如果今天想要使用電腦,該怎麼做?
你的答案很可能是,按下電腦開機鍵就好,但實際上得先有主機、滑鼠、鍵盤、螢幕、電源、作業系統…等軟、硬體環境,才有辦法使用電腦。
JavaScript 雖然是直譯式語言(不需透過編譯器轉譯成可執行檔),但是『執行』之前,還是需要先把原本字元組成的程式碼編譯成執行環境(就像是上面提到的準備滑鼠、鍵盤…等等),而其中一個步驟就是先將 變數
和 函數
的名稱放入記憶體,這種行為在 ECMA 的文件中沒有明確定義專有名詞,一般會用 提昇(Hoisting)
來稱呼。
參考文章:
MDN - 提升(Hoisting)
提昇(Hoisting)的方式會因為變數類型有所不同:
💎 var、function:
按照逐行執行的邏輯,下面前兩行程式碼會因為還沒有產生這個變數而出現錯誤,但實際上並不會出現任何錯誤。
1 | console.log(a); // undefined |
從結果回推實際執行的順序會像下面這樣:
1 | var a; |
這次做小調整,改成賦予 a 變數一個值
1 | console.log(a); // undefined |
雖然沒有出現錯誤,但是 a 的值並沒有跟著被提昇,回推的執行順序會像下面這樣:
1 | var a |
再看下面這段程式碼,想想看結果是什麼:
1 | var b = 1; |
如果不清楚運作 JavaScript 的運作機制,可能會認為答案是 undefined
,覺得後者蓋掉前者,但答案其實是 1
,回推後的實際執行會像是下面這樣:
1 | var b; |
『重複宣告』加上『提昇機制』是不是讓人覺得很坑呢?
💎 let、const:
ES6 版本提供了 let
和 const
兩種變數宣告方式,這兩種新的方式解決了 var
的許多奇怪問題。
使用 let
和 const
宣告的變數名稱在 JavaScript 從『環境建立』一直執行到『變數實際存在的那一行程式碼』的這段期間,變數名稱都是無法被取用的,這段期間稱為 Temporal Dead Zone(TDZ),暫時性死區。
這個機制就像是我買了對號座的票(宣告),這個位置的票就不能被其他人購買(不能重複宣告),但是在我坐上車位前(實際執行的那段程式碼),都無法在這個位置找到我(TDZ鎖定)。
以下是使用 let
或 const
宣告的輸出結果:
1 | console.log(x); // x is not defined |