前言
2021-06-09 補充:
感謝讀者 blackr1234 留言,此文章為 2018 年 11 月發表,底下程式碼輸出結果大概是以 Node.js v8.17.0 為準,因此對於一些狀況的輸出可能會跟現在不太一樣。例如說存取宣告前的 let 變數,當初的結果為:ReferenceError: a is not defined
,現在用 Node.js v14 的結果則是:ReferenceError: Cannot access 'a' before initialization
。
這陣子我在忙一些教學相關的東西,稍微準備一些資料之後教了學生們 JavaScript 裡面的 hoisting,也就是「提升」這個觀念,例如說以下程式碼:
console.log(a)
var a = 10
會輸出undefined
而不是ReferenceError: a is not defined
,這種現象就叫做 Hoisting,變數的宣告被「提升」到最上面去了。
如果你只想了解最基本的 hoisting,其實差不多就是這樣,但後來我還教了let
跟const
相關的一些知識,不過前一天剛教學完,隔天就立刻看到相關的技術文章還發現自己教錯,因此特別花了一點時間打算好好理解 hoisting 這個東西。
很多東西沒有深入研究的時候你都會覺得沒什麼,真的跳下去深入去看才會發現自己其實還有一大堆概念沒有搞懂。
有很多人都知道 hoisting,但是理解程度卻不盡相同,我列出了 10 個項目,如果有任何一點你剛好不知道的話,那恭喜,這篇文章應該可以為你帶來一些收穫。
- 你知道什麼是 hoisting
- 你知道 hoisting 只會提升宣告而非賦值
- 你知道 function 宣告、function 的參數以及一般變數宣告同時出現時的提升優先順序
- 你知道 let 跟 const 沒有 hoisting
- 你知道第四點是錯的,其實有但只是表現形式不一樣
- 你知道有關第五點,有個概念叫做 TDZ(Temporal Dead Zone)
- 你看過 ES3 的規格書,知道裡面是怎麼描述的
- 你看過 ES6 的規格書,知道裡面是怎麼描述的
- 你知道 hoisting 背後的原理是什麼
- 你看過 V8 編譯出來的程式碼
你可能會問說:「我為什麼要知道的這麼深?有什麼用?」,其實我也覺得對 hoisting,只要知道基本的就行了。只要你有好好地宣告變數,就算不知道那些,對日常生活或是工作也不會有太大的影響。
可是假如你像我一樣,想要有朝一日在自己的履歷上面放上「精通 JavaScript」的話,那對這些東西就不能逃避。同時你如果對底層的這些細節愈熟悉,會碰到的問題就愈少,也愈能理解為什麼會有 hoisting 的出現,當你想要在技術這條路上走得更遠爬得更高時,我覺得這些細節是很重要的。
接下來,我們就一步步來看 hoisting 吧!