EP.23 RE:從零開始的學習 JS 生活-第二十三日之 Hoisting

前言

轉生第二十三日,接下來這一篇將會介紹 Hoisting。

Hoisting

首先前面這邊先大概提一下 JavaScript 的運作流程

  • 首先全域執行環境會被先建立,也就是 window
  • 語法解析器開始分析我們的程式內容,例如 f-u-c-t-….(逐字解析…)
  • 編譯器開始將我們所撰寫的程式轉換電腦可以看懂得指令
  • 開始創造「全域執行環境」,這時候會建立 windowthis
  • 再來就進入 Hoisting

關於語法解析器可以參考我先前寫的其他文章:[JS奇怪的世界]No.1 觀念小提醒:語法解析器、執行環境、詞彙環境

那什麼是 Hoisting 呢?Hoisting 可以細分主要兩個階段

  • 創造階段
  • 執行階段

前面我們知道一開始 JavaScript 在執行環境會優先建立 windowthis,接下來就會開始進入 Hoisting 的兩階段,舉例來講,我們目前所撰寫的程式碼如下:

1
2
3
4
5
6
7
a();

function a() {
console.log('函式 A');
}

var b = 1;

當 JavaScript 讀取完我們所有的程式碼就會開始依序準備相關記憶體,那麼如果我們直接將程式碼貼到系統內執行,其實你會發現一件很奇妙的事情,也就是我明明是在函式之前呼叫函式,但卻不會出現錯誤,反而還能夠正常呼叫 ↓

函式 A

那這個原因最主要是出在 JavaScript 的 Hoisting 特性所導致,程式碼在運行時,會被劃分為兩階段,第一階段是創造並提升函式與變數,然後第二階段則是執行程式碼,但是這邊有一個重點要記得函式比變數有更高的優先度,所以會被提升至比變數更前面,所以實際運行的程式碼是像這樣:

1
2
3
4
5
6
7
8
9
// 創造 & 提升階段
function a() {
console.log('函式 A');
}
var b;

// 執行階段
a();
b = 1;

所以我們可以知道一件事情,JavaScript 在執行時會先經歷過 Hoisting 的兩階段,最後才會在執行階段將相關的變數賦予值或是執行其他動作,另外 Hoisting 在 MDN 的文件上有解釋,以下擷取 MDN 片段

提升看起來是單純地將變數和函式宣告,移動到程式的區塊頂端,然而並非如此。變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。

MDN 原文

所以由此可知 Hositing 會跟記憶體有關係,因為 JavaScript 在執行前,會先將變數和函式提升至最前面並儲存在記憶體中,後面再依照相對應做賦值或處理,但是並不會將程式碼改變位子唷~

結尾

下一篇的 RE:從零開始的學習 JS 生活-第二十四日 將會介紹 undefined 與 not defined 的差異。