五分鐘輕鬆暸解「提升(Hoisting)」!
「獻給 JS 新手的五門底層運作課」系列文章之三
p.s. 如果你還不暸解什麼是
執行環境 (Execution Context)
,建議你先閱覽上一篇文章,有了相關的基礎之後,再閱讀本篇文章。
在上一篇『秒懂!JavaScript 執行環境與堆疊』中,我們淺談了:
- 執行環境 (Execution Context)
- 執行堆疊 (Execution Stack)
同時也有提到,執行環境
在建立時會經歷兩個階段,分別是:
- 創造階段 (Creation Phase)
- 執行階段 (Execution Phase)
執行階段 (Execution Phase) 顧名思義,就是一行一行地執行程式碼,這沒什麼困難的。不過在那之前,還有一個相當重要的階段,稱作創造階段!傳說中的 提升 (Hoisting)
就是在這個階段發生的。
那究竟創造階段(Creation Phase) 是在創造什麼呢?
執行環境物件
還記得上一章,我提過一個叫做 執行環境物件
傢伙嗎?
每個執行環境都會配有一個執行環境物件 (Execution context object),
負責紀錄該環境中需要用到的各種資料。
由於需要紀錄的資料相當得多,所以 執行環境物件
就必須好好地為這些資料分類,讓 執行環境
能更快速、更明確地取得它需要的資料。
因此,每個 執行環境物件
都有 3 個屬性 (Property),分別是:
- 變數物件 (Variable Object)
- 作用域鏈 (Scope Chain)
- “This” 變數 (“This” Variable)
我知道這三個屬性聽起來都很不友善,但概念其實非常地簡單,相信你讀完這一系列的文章後,就會很有感覺。
這個章節我們會著重在 執行環境物件
的第一個屬性:
Variable Object 變數物件。
Variable Object 變數物件
剛剛我們有提到:「Variable Object
、Scope Chain
與 “This” variable
三大巨頭,分工合作地為 執行環境
記錄許多相當重要的資料。」對吧?
接下來,我們會用平易近人的方式介紹 Variable Object
究竟負責哪些資料,抓點零食,我們開始吧!
Variable Object
負責三件事:
- 建立
Argument Object
,存放所有我們打算送進函式的引數 (Argument)
。 - 掃描程式碼中是否有
函式宣告 (Function Declaration)
:如果有,就為每一個函式建立一個新屬性,其值指向該函式在記憶體中的位址。 - 掃描程式碼中是否有
變數宣告 (Variable Declaration)
:如果有,就為每一個變數建立一個新屬性,並將該屬性的值初始為undefined
。
而最後兩項在程式界中,有一個響叮噹的名號:Hoisting(提升)。
提升 Hoisting
Hoisting(提升)
聽起來好像很牛,其實概念非常簡單:
- 變數與函式,在進入執行階段前,其實就已經完成宣告。
- 這種「將變數宣告與函式宣告的動作,提升到程式碼最頂端」的行為,就是
Hoisting(提升)
。
而 Hoisting(提升)
,其實也解答了許多 Javascript 初學者的疑惑:
為什麼有些函式在宣告式之前就可以進行呼叫?
答案就是:
這些函式早就在執行階段前,就已經被宣告並儲存在 Variable Object
中。
那函式的 Hoisting(提升)
與變數的 Hoisting(提升)
,差在哪裡呢?
- 函式在建立階段時,就已經獲得明確的定義,另一方面,變數在創造階段還不會被賦予它們應有的值,而是統一初始化為
undefined
,直到執行階段時,變數才會隨著程式碼的讀取而被賦予明確的值。
本堂精華:1 分鐘課後複習
執行環境
的建立會經歷兩個階段:1) 創造階段、2)執行階段。- 每個
執行環境
都會有一個執行環境物件
,幫忙記錄該環境中的資料。 - 執行環境物件有三個屬性:
變數物件 (Variable Object)
、作用域鏈 (Scope Chain)
與“This” 變數
。 變數物件 (Variable Object)
有三個任務:協助紀錄函式引數、完成函式與變數宣告,並將所有變數值初始為undefined
。Hoisting(提升)
指的是:變數與函式,在進入執行階段前,其實就已經完成宣告。- 函式的
Hoisting(提升)
與變數的Hoisting(提升)
,差在變數在這個階段還未獲得明確的定義,統一初始為undefined
,而函式已獲得完整定義。
Takeaway
暸解為什麼有些函式和變數在宣告式之前就可以進行呼叫?
預告:
下一章節,我們會聊到執行環境物件中的第二個屬性:作用域鏈 (Scoping Chain),為何它會被形容成家族族譜?我們將由淺入深,讓你能瞬間掌握這些抽象到不行、卻重要到不行的「JS 底層運作原理」。
如果這篇文章有幫助到你的話,是我最大的榮幸。
請用長按「拍手 (Clap)」的方式讓我知道你對這篇文章的喜愛!
也歡迎路過的大神們能給予技術方面的建議,謝謝你們的觀看。