首頁 > web前端 > js教程 > 主體

JavaScript引擎

WBOY
發布: 2024-09-01 21:13:37
原創
696 人瀏覽過

JavaScript Engine

JS引擎:

  • 執行JS程式碼的程式。前任。谷歌的 V8。
  • V8 為 Chrome、Node.js 提供支援
  • 其他瀏覽器有自己的 JS 引擎。

JS 引擎有 2 個部分:

  1. 呼叫堆疊:使用執行上下文執行我們的程式碼的地方。
  2. 堆:非結構化記憶體池,用於儲存物件。

每個c/r程式都需要轉換為機器碼。透過兩個過程完成:

1.編譯:將整個程式碼一次轉換為機器碼,寫入電腦可以執行的二進位。

原始程式碼 -(已編譯)->二進位程式碼[可移植檔] -(已執行)-> PGM 運行
執行可以在編譯後發生。

2.解釋:解釋器遍歷原始程式碼,逐行執行。

原始碼-(逐行執行)-> PGM 運行

  • 這裡程式碼還需要轉換成機器碼。
  • 與編譯的 l/gs 相比,它們要慢得多。

3. JIT 即時編譯:

  • 現代 JS 引擎是編譯和解釋的結合,使其速度更快。
  • 整個程式碼立即轉換為機器碼,然後立即執行。 原始碼-(編譯)->機器碼-(執行)-> PGM 運行
  • 沒有要執行的中間可移植檔。
  • 編譯後立即執行。
  • 因此,由於這種技術,JS 現在比解釋的 l/gs 快得多。

JS中的編譯過程:

步驟1.解析:

  • 我們的程式碼被解析,即由 JS 引擎讀取為 AST 或抽象語法樹。
  • 根據 const、let、function 等對 l/g 有意義的關鍵字將程式碼拆分為樹。
  • 然後將程式碼以結構化的方式儲存到樹中。
  • 也要檢查是否有任何語法錯誤。
  • AST 與 DOM 樹無關。 AST 只是 JS 引擎內代碼的表示。

步驟2、3[組合]:編譯+執行

  • AST 會使用 JIT 進行編譯並立即執行。
  • 執行發生在呼叫堆疊中。
  • 現代JS有巧妙的最佳化策略,即在開始時快速建立未最佳化版本的機器碼,以便盡快開始執行。
  • 在後台,此程式碼在已執行的 pgm 執行期間再次重新編譯。
  • 透過多次迭代完成,每次最佳化後,未最佳化的程式碼都會與新最佳化的程式碼交換,而不會停止程式碼執行。這使得 V8 如此之快。
  • 所有這些解析、編譯、執行都發生在 JS Engine 內的某個特殊執行緒中,我們無法使用與使用呼叫堆疊運行程式碼的主執行緒完全分開的程式碼來存取該執行緒。
  • JS 不再只是解釋 l/g。它具有 JIT 編譯,這使得它比解釋的 l/gs 更快。

JS 運行時 = JS 引擎 + Web API + C/B 佇列

  • JS Runtime:包含我們使用 JS 所需的所有東西的容器。
  • 任何 JS 運行時的核心都是 JS Engine。
  • 沒有 JS Engine,就沒有運行時,因此根本就沒有 JS。
  • 僅 JS 引擎是不夠的,我們需要存取 DOM、Fetch、Timers 等 Web API。
  • Web API:執行時期提供給引擎的功能,但不是 JS 引擎的一部分。前任。瀏覽器中的視窗對象,節點中的全域對象。
  • 回呼佇列是一個包含所有準備執行的函數的資料結構。前任。點選、計時器、資料等
  • DOM 事件處理函數 fns 也稱為回呼 fns。
  • 當Call stack為空時,回呼fn從C/B佇列轉移到Call stack執行。
  • 持續的檢查和移位是由事件循環執行的。
  • 事件循環是讓 JS 擁有非阻塞並發模型的東西。
  • 對於node,我們沒有瀏覽器提供的Web API。我們有一個叫做 C++ 綁定和線程池的東西。

JS 程式碼如何在呼叫堆疊上執行

  • JS 有單執行緒執行,因此一次只能做一件事。因此,JS 中沒有多重詢問。
  • API是由環境提供的,而不是語言的一部分。前任。 Web API,如計時器、Fetch、DOM、地理位置等
  • 回呼佇列:準備執行回呼函數,附加到已發生的某些事件。
  • 每當呼叫堆疊為空時,事件循環就會將回呼從回呼傳送到佇列,然後再呼叫堆疊來執行。
  • 因此,事件循環是使 JS 中的異步行為成為可能的重要組成部分。
  • 並發模型:l/g 如何處理同時發生的多個事件。
  • JS Runtime 的基本部分:
  • 呼叫堆疊
  • Web API
  • 回呼隊列
  • 事件循環
  • 與 DOM 相關的所有內容都是 Web API 的一部分,而不是 JS。
  • 圖像加載以非同步方式進行,如果以同步方式加載,那麼它會被阻塞,即不在主線程上,而是在 Web API 環境上。
  • 所有事件監聽器、.then() 等工作都發生在 WEb API 環境中,而不是在呼叫堆疊上。
  • 回呼函數被放置在回調佇列中等待它們在呼叫堆疊上執行。
  • 回呼佇列就像一個呼叫堆疊必須完成的待辦事項清單。
  • 這裡提到的持續時間是執行前的最小延遲,而不是執行的時間。
  • 回呼佇列還包含來自 DOM 事件、點擊、按鍵等的回呼。 DOM 事件不是異步為,但它們使用回呼佇列來執行。
  • 事件循環不斷檢查回呼佇列直到其為空。放置在呼叫堆疊上的每個回調稱為事件循環標記。
  • 事件循環協調整個 JS 運行時。
  • JS 本身沒有時間概念,因為非同步程式碼不在引擎中執行。運行時管理異步行為,事件循環決定執行哪個回呼。
  • 引擎或呼叫堆疊只是執行給它的程式碼。
  • 當要載入映像時,事件偵聽器會在 Web API 環境中持續等待,直到觸發載入事件。當它被觸發時,只有它作為回調 fn 進入回調佇列,等待輪到它在呼叫堆疊上執行。

微任務隊列:

  • 來自 Promise 的回呼不會進入回呼佇列,而是進入微任務佇列。
  • 該佇列的優先權高於回呼佇列。
  • 事件循環首先檢查此佇列,先執行其所有任務,然後轉到回呼佇列執行。
  • promise 的回呼稱為微任務,因此稱為微任務佇列。還有其他微任務,但目前與此處無關。 事件循環決定每個回調何時執行。與回調隊列相比,它為微任務提供了更高的優先權
  • 微任務可以在所有其他常規回調隊列之前進行內聯切割。
  • Promise.resolve() :建立一個立即解決的 Promise,其成功值作為參數傳遞到其中。 then() 回呼被調用,並以解析值作為參數。
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise").then(res => console.log(res));
console.log("Direct simple console END");

Order of Output:
Direct simple console BEGIN
Direct simple console END
Text from Promise
undefined
Text from Timer
登入後複製
  • 如果微任務佇列中有大量微任務或耗時的微任務,微任務佇列甚至可能會導致回呼佇列挨餓。
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise1").then(res => console.log(res));
Promise.resolve("Text from Promise2").then(res => {
  for(let i=0; i<5000; i++)
  console.log(res);
});
console.log("Direct simple console END");
登入後複製

以上是JavaScript引擎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!