JavaScript 變數提升 Variable Hoisting

變數的提升(Hoisting)

在其他程式語言裡面,程式碼是逐步執行的,所以「把要做的事情放在宣告之前」,就會出錯。

但在 JavaScript 並不會出錯,因為執行程式碼之前,會先把宣告的函式或變數放到記憶體中,直到程式執行的時候,函式或變數就已經存在了。(感覺像是宣告的東西被提升到要做的事情之前,但實際不是)

要做的事情放在宣告之前,仍然可以繼續執行的現象叫做提升(Hoisting)

1
2
3
4
5
sayHello() // Hello!

function sayHello(){
console.log("Hello!");
}

var 的提升(Hoisting)

在宣告 var 變數之前取用值,會得到 undefined

要注意的是,變數只有宣告(宣告指的是var a;)會被提升,因為變數本身還沒有到執行階段,還沒有被賦值(賦值指的是a=0;),所以在宣告之前就取值,我們會得到 undefined

用範例的執行過程來說,JavaScript 在程式執行之前,先把 a 放到記憶體中,並給予值 undefined;在執行階段的時候,由於 a 這個變數還沒執行到 a = 0 就被取用了,所以取到的值是 undefined

1
2
3
console.log(a) // undefined
var a = 0;
console.log(a) // 0

let/const 的提升(Hoisting)

在宣告 let/const 變數之前取用值,會直接拋出 Error。

雖然宣告的變數在執行之前已經放到記憶體了,但 JavaScript 並不會把 let/const 的值定為undefined,而是暫時不讓你存取。

以結果來看,let/const 確實有 Hoisting 的效果,因為並不是找不到宣告的 let/const 變數,只是暫時不能被存取。這種「從宣告變數到初始化完成之前還不能存取」的限制,叫做暫時死區(TDZ - temporal dead zone)。

1
2
3
console.log(a) // Cannot access 'a' before initialization
let a = 0;
console.log(a)

參考資料

我知道你懂 hoisting,可是你了解到多深?

let - JavaScript | MDN

var - JavaScript | MDN

Day22【ES6 小筆記】變數提升(Hoisting)與暫時死區(TDZ) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

理解ES6中的暫時死區(TDZ) | Eddy 思考與學習

提升(Hoisting) - 術語表 | MDN