
JavaScript Hoisting 提升
什麼是提升 Hoisting
Hoisting 指的是,JavaScript 在執行程式碼之前,先掃瞄整個作用域,並將宣告拉到作用域最上方的行為。
Hoisting 只會提升宣告,不會提升賦值。
但是一定要注意,前面提到的「拉到上方」並不真正的搬動程式碼!! 因為 JavaScript 在執行前會先建立執行環境(Execution Context),這時需要先替變數與函式配置記憶體空間,因此會出現這種「宣告被搬到前面」、「宣告的程式碼看起來可用」的狀況。
變數宣告的提升
var 的提升
範例
console.log(a);
var a = 10;
結果
undefined這個例子中,程式會正常執行不報錯,但是印出 undefined。
因為 var 宣告的 a 被提升了,而賦值的程式碼還留在原地, JS 執行起來會像是:
var a; // 宣告被提升
console.log(a); // 嘗試印一個還沒被賦值的 a
a = 10; // 賦值
這也是為何會出現 undefined 的原因。
let/ const 的提升
let 範例
console.log(b);
let b = 10;
let 結果
ReferenceError: Cannot access 'b' before initialization
const 範例
console.log(c);
const c = 10;
const 結果
ReferenceError: Cannot access 'c' before initialization
從結果看來,不論是 let 與 const,兩者在宣告前嘗試先存取變數都會出現錯誤,這是因為 let 與 const 雖然在提升時期都會被建立,但是並沒有被初始化,這段期間也被稱做進入暫時死區 temporal dead zone。
函式宣告的提升
函式宣告式 Function declaration 的提升
函式宣告式指的是用 function 關鍵字宣告的有名函式。函式宣告式會被提升,所以可以在程式中的任一地方呼叫,如下方範例:
sayHi();
function sayHi(){
console.log("Hi");
}
這段程式的結果可以正確印出 "Hi" ,因為整個函式都被提升。
函式表達式 Function expression 的提升
另一種宣告函式的方法叫做函式表達式,意思是將函式賦值到宣告的變數。在這種宣告方式下,指有被宣告的變數會被提升,函式內容還停留在原地,因此會出現錯誤。
但是具體報錯的訊息會取決自接受的變數類型
sayHi();
var sayHi = function(){
console.log("Hi");
}
以 var 的範例來說,會出現:
TypeError: sayHi is not a function
而將變數替換為 let/const 宣告,則會出現:
ReferenceError: Cannot access 'sayHi' before initialization
總結
JavaScript 在建立執行環境時會將變數、函數的宣告邏輯移到作用域頂端,這樣的情況稱作提升 Hoisting。
- 變數、函式的宣告都會有提升情況
- 只有宣告會提升,「賦值」不會被移動
- var 在提升時會初始化成 undefined
- let/const 不會初始化,會進入暫時死區 temporal dead zone
- 函式宣告式 function declaration 會被完整提升,函式表達式則只有宣告會被提升
參考












