ItIron2021
Javascript
昨天我們簡單探討了一下程式語言間常常出現的浮點數問題,同時也回味了一下火影忍者的某個角色,今天讓我們繼續藉由簡單的面試題目來了解另一個你可能知道、卻並不是那麼熟悉的概念吧!
請解釋javascript中提升(hoist)的概念
老樣子來個防雷圖,思考結束後再往下滑吧!
這同樣也是一個js中基本的核心概念之一,用簡單的一句話來說就是
在執行程式碼之前(也就是編譯階段),把所有的宣告程式碼(declarations)放入記憶體的位置中
這讓我們有辦法在函數/變數宣告前就先行使用該函數/變數,舉個簡單的例子
add(1,3) // 4
function add(a, b) {
console.log(a + b)
}
在還沒有運行到該行函數宣告時,我們就已經可以正確使用add函數了!
你可以想像上述的程式碼變成以下的結構
function add(a, b) {
console.log(a + b)
}
add(1,3) // 4
這種彷彿把函數/變數的宣告(declarations)移到該作用域的最上方的行為就稱作提升,注意我用的詞是彷彿,因為事實上程式碼的實際位置並沒有移動,只是先行被放到記憶體的位置造成了這樣的結果。
若是要應付基本的問答,上述的說法可說是提升的最基礎概念,應該足以你過關了,那麼試著面對以下的問題吧!
只有函數宣告會被提升嗎?
照文章的鋪陳,我想你也知道答案肯定是否定的。變數的宣告自然也會提升,我們同樣看個簡單的例子吧!
console.log(a)
var a = 3
若你覺得答案應該是3,那表示你需要繼續往下看這篇文章?
上方的程式碼可以用以下的結構理解,由於提升的關係,宣告的部分會先被放到記憶體位置(或是你想理解為移到該作用域的最上方也行!)
var a
console.log(a)
a = 3
提升的部分僅有宣告的行為,賦值是沒有一併被提升的! 而我們知道宣告變數卻不賦值的話,該變數的值會是undefined,最終印出undefined這樣的結果!
OK! 現在你理解變數的宣告同時也會被提升,再看看下一個進階一點的問題吧!
那let & const的宣告也會被提升嗎?
這裡開始就是個分歧點了,因為不少人會跟你說只有var宣告的變數會被提升。
首先先說結論,所有變數的宣告都會被提升,我們一樣用個實例來證明吧!
function demo() {
console.log(a)
const a = 5
}
假設const/let宣告的變數並沒有提升的行為,那麼我們在執行該函數時想必就會出現一個錯誤告訴我們a這個變數未被定義吧!也就是我們熟悉的那個錯誤訊息
Uncaught ReferenceError: a is not defined
但實際上去執行函數時你會發現跟你想像的並不一樣
Uncaught ReferenceError: Cannot access 'a' before initialization
簡單翻譯就是你沒辦法在a變數尚未被賦值前就嘗試使用該變數,綜合我們之前的理解,這表示a變數確實也經過提升而被放到記憶體位置,只是let/const在被提升的行為與var並不相同,var宣告的變數被提升後,預設的行為就是給予undefined這個值作為初始化,相對的let/const並沒有這樣的初始化,且若是在被賦值前被嘗試存取則採用丟出一個錯誤作為預設的處理方式,這樣一個小小的區間(被賦值前被嘗試存取)就被稱為所謂的暫時性死區(Temporal Dead Zone),它聽起來很潮但沒什麼特別的,就僅是說明let/const被提升的行為有所不同的一個名詞而已。
提升(hoist)、變數宣告與賦值、暫時性死區
本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!
今天的文章中較進階的內容主要來自以下的文章,在我初學hoist的時候幫我了大忙