JS: Hoisting & TDZ

Hoisting是指變數在被宣告以前就能被存取,造成hoisting的原因就跟之前提過的執行環境(execution context)有關。

曾經談過程式碼在執行以前會先建立執行環境,執行環境中的variable environment object會儲存var, let, const變數、函式定義、函式引數物件(arguments object),因此在 執行 程式碼以前,程式碼的變數和函式定義早已在建立執行環境時就被儲存了,所以執行時才會看起來像是變數在宣告之前就可以被存取。

下表整理不同變數的hoisting行為,理論上每種類型的變數都有hoisting只是表現不同,若在宣告之前存取變數,因為還不知道變數宣告的值所以會有初始值(initial value),例如:

scope chain

  • Hoisting表徵最明顯的是函式宣告式(function declaration)和var變數(var variable),但因為函式宣告式的定義會在建立執行環境的階段就儲存,所以函式宣告式hoisting的初始值即是函式宣告式的定義;

  • var變數hoisting的初始值則是 undefined,不過 undefined 很容易造成應用程式的錯誤,所以現代程式碼已經不鼓勵使用var變數。

  • let、const變數在技術上也有hoisting行為,但是let、const變數在宣告以前被存取的程式碼會被視為是TDZ(temporal dead zone)、未初始化(uninitialized),因此若在let、const變數被宣告以前就存取就會報錯。

  • 最後是函式表達式(function expression)和箭頭函式(arrow function),這兩種函式的hoisting行為和初始值取決於是被var、let或const宣告,若是以var宣告並在宣告之前就存取會取得undefined為值,若是以let、const宣告則是會報錯。


References The Complete JavaScript Course 2023: From Zero to Expert!