前端-JavaScript執行原理

程式設計碼農發表於2021-10-28

簡介

理解JavaScript執行原理,我們需要理解以下兩方面內容。

  • JavaScript引擎。
  • JavaScript執行時環境。

JavaScript引擎

什麼是JavaScript引擎

JavaScript引擎是一個計算機程式,它的主要作用是JavaScript執行時將原始碼編譯為機器碼。

每個主流Web瀏覽器都有自己的JavaScript引擎,它通常由web瀏覽器供應商開發。

主流web瀏覽器

  • Google Chrome V8。
  • Mozilla Firefox Spider Monkey。
  • Safari Javascript Core Webkit。
  • Edge (Internet Explorer)

以前的JavaScript引擎主要在web瀏覽器使用,不過隨著nodejs的出現就打破了這種侷限。

V8引擎

V8包含了解析器(parser),直譯器(Ignition),優化編譯器(TurboFan )。

解析器(parser):用於生成抽象語法樹。

JavaScript程式碼的句法結構的樹形表示形式

直譯器(Ignition):將原始碼轉換為位元組碼。

直譯器

優化編譯器(TurboFan ):進行一些優化編譯優化處理,比如內聯快取。

下面是V8引擎的大體工作流程。

  1. 首先解析器先生成一個抽象語法樹。
  2. 然後直譯器根據語法樹生成V8格式的位元組碼。
  3. 優化編譯器再將位元組碼編譯成機器碼。

原始碼轉化為機器碼流程

執行時環境

瀏覽器執行環境中,瀏覽器提供了Web API,如:HTTP請求,計時器,事件等。

伺服器執行環境中,nodejs提供了API。

下面是JavaScript在瀏覽器中執行時的架構,它包含一個記憶體堆、一個記憶體棧、一個事件迴圈、一個回撥佇列。

JavaScript執行時架構

  • 記憶體棧(stack),一個連續的記憶體區域,為每個執行的函式分配本地上下文。
  • 記憶體堆( heap), 一個更大的記憶體區域,儲存動態分配的所有內容。
  • 呼叫棧(call stack), 一種資料結構,記錄了我們在程式中的位置。
  • 回撥佇列(callback queue),儲存非同步任務的回撥函式。
  • 事件迴圈(event loop),持續檢查呼叫棧是否為空,如果為空,將回撥佇列中頭部回撥函式移動到呼叫棧執行。

執行時的呼叫棧

下面程式碼展示了JavaScript執行的呼叫棧變化。

JavaScript呼叫棧

function add(x, y) {
    return x + y;
}

function print(x, y) {
    console.log('x+y=',add(x, y))
}

print(1, 3)

非同步任務

JavaScript先執行了print函式,然後呼叫Web API setTimeout(),Web API儲存了setTimeout() 的回撥函式,3秒後將回撥函式新增到回撥佇列,事件迴圈發現呼叫棧為空,於是將佇列裡的回撥函式移至呼叫棧執行。

非同步任務

function add(x, y) {
    return x + y;
}

function print(x, y) {
    setTimeout(function (){
        console.log('x+y=',add(x, y))
    }, 3000)
}

print(1, 3)

小結

JavaScript執行主要依靠JavaScript引擎和執行環境,引擎將js原始碼翻譯成計算機所理解的機器碼,執行環境提供了一些與計算機底層通訊的API和執行實現。

相關文章