在 JavaScript 中有很多程式碼運作的方式,讓我們一起來瞭解看看吧!
Example.1
從以下例子中你會發現印出的結果,竟然會是在全域宣告的變數 x = 2,
因為在執行程式碼之前(編譯的階段),把所有宣告的程式碼放入記憶體的位置,這個動作叫做提升(Hoist),
而 function f() 內部沒有 x 變數,故往 function 外查找的動作叫做範圍鏈(Scope Chain),
最後得到 x = 2 的數值後印出,過程如下:
// 宣告全域變數 x 為 2。 let x = 2 function f(){ // 印出變數 x 的值,此時區域作用域中查無此變數,故往外查找全域變數 x 的值,即為 2。 console.log(x); //2 } // 執行函數 f()
Example.2
以下程式碼中,第一個 console 往外查找了 x = 2 的變數賦值,再來經過了 x = 3 的重新賦值,
最後執行第二個 console 的結果,過程如下:
// 宣告全域變數 x 為 2。 let x = 2 function f(){ // 印出變數 x 的值,此時區域作用域中查無此變數,故往外查找全域變數 x 的值,即為 2。 console.log(x); //2 // 對變數 x 進行重新賦值,由 2 改為 3。 x = 3 // 印出變數 x 的值,此時 x 的值,即為 3。 console.log(x); //3 } // 執行函數 f()
Example.3
我們一步一步拆解以下程式碼執行的過程:
1. 宣告全域變數 x,賦值為 2。
2. 定義函數 f()。
3. 在函數 f() 中的第一個 console.log(x) 嘗試訪問變數 x,但因為該變數在初始化之前的 TDZ 中,所以拋出錯誤。
4. 在函數 f() 中宣告區域變數 x,賦值為 3。
5. 在第二個 console.log(x) 中,印出區域變數 x 的值,即 3。
6. 呼叫函數 f()。
// 宣告全域變數 x 為 2。 let x = 2; function f() { // 印出變數 x 的值,此時 JavaScript 會在函數範圍內優先使用該區域變數(let x = 3), // 但是受到變數提升 (hoisting) 的影響,該變數被先行宣告,但尚未執行初始化賦值(let x = 3), // 此時處於暫時性死區 (Temporal Dead Zone, TDZ),因此無法訪問 x 的值,並拋出錯誤。 console.log(x); // Cannot access 'x' before initialization // 宣告局部變數 x 為 3。 let x = 3; // 印出變數 x 的值,此時 x 為區域變數的值,即為 3。 console.log(x); //3 } // 執行函數 f();