JS: Hoisting & TDZ
Hoisting是指變數在被宣告以前就能被存取,造成hoisting的原因就跟之前提過的執行環境(execution context)有關。
曾經談過程式碼在執行以前會先建立執行環境,執行環境中的variable environment object會儲存var, let, const變數、函式定義、函式引數物件(arguments object),因此在 執行 程式碼以前,程式碼的變數和函式定義早已在建立執行環境時就被儲存了,所以執行時才會看起來像是變數在宣告之前就可以被存取。
下表整理不同變數的hoisting行為,理論上每種類型的變數都有hoisting只是表現不同,若在宣告之前存取變數,因為還不知道變數宣告的值所以會有初始值(initial value),例如:
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!