為網頁編寫程式碼有時感覺有點神奇,因為我們在文件中編寫字元序列,在瀏覽器中開啟該文件,然後觀看它的實作。但了解魔法背後的技術可以幫助你更好地磨練你作為程式設計師的手藝。
在本文中,您將透過掌握支援瀏覽器的 JavaScript 引擎的複雜性,了解 JavaScript 驅動的 Web 或行動堆疊幕後發生的事情。讓我們來分析一下 JavaScript 引擎的作用,為什麼不同的平台使用不同的引擎,它們多年來是如何發展的,以及為什麼我們作為開發者應該關心。
「JavaScript 引擎」通常被稱為虛擬機器的一種。 「虛擬機器」指給定電腦系統的軟體驅動模擬。虛擬機器有很多類型,它們根據模擬或替代實際實體機的精確程度進行分類。
例如,「系統虛擬機器」提供了可以執行作業系統的平台的完整模擬。 Mac 使用者可能熟悉 Parallels,這是一個系統虛擬機,可讓您在 Mac 上執行 Windows。
另一方面,「進程虛擬機器」的功能不太齊全,只能執行一個程式或進程。 Wine 是一個進程虛擬機,可讓您在 Linux 機器上執行 Windows 應用程序,但不會在 Linux 機器上提供完整的 Windows 作業系統。
JavaScript 引擎是一種專門用於解釋和執行 JavaScript 程式碼的進程虛擬機器。
注意:區分透過佈局網頁來驅動瀏覽器的引擎與解釋和執行程式碼的低階 JavaScript 引擎非常重要。這篇關於瀏覽器如何運作的文章提供了很好的解釋。
那麼 JavaScript 引擎到底是什麼?它有什麼作用?
總而言之,JavaScript 引擎的基本工作是獲取開發人員編寫的 JavaScript 程式碼,並將其轉換為可以由瀏覽器解釋甚至嵌入到應用程式中的快速、優化的程式碼。事實上,JavaScriptCore 稱自己為「優化虛擬機器」。
更準確地說,每個 JavaScript 引擎都實作一個 ECMAScript 版本,JavaScript 是其中的一種方言。隨著 ECMAScript 的發展,JavaScript 引擎也不斷發展。之所以有這麼多不同的引擎,是因為每個引擎都設計用於不同的 Web 瀏覽器、無頭瀏覽器或 Node.js 等執行階段。
您可能熟悉網頁瀏覽器,但什麼是無頭瀏覽器?它是一個沒有圖形使用者介面的網頁瀏覽器。它們對於針對您的網路產品執行自動化測試非常有用。從 Chrome 版本 59 和 Firefox 版本 56 開始,常規瀏覽器可以以這種方式使用,特別是用於測試。 Node.js 在哪裡適合這個? Node.js 是一個非同步、事件驅動的框架,可讓您在伺服器端使用 JavaScript。由於它們是 JavaScript 驅動的工具,因此它們由 JavaScript 引擎支援。
考慮到上面虛擬機器的定義,將 JavaScript 引擎稱為進程虛擬機器是有意義的,因為它的唯一目的是讀取和編譯 JavaScript 程式碼。這並不意味著它是一個簡單的引擎。例如,JavaScriptCore 有六個“構建塊”,用於分析、解釋、優化和垃圾收集 JavaScript 程式碼。
這取決於引擎。讓我們考慮兩個重要的引擎:WebKit 的 JavaScriptCore 和 Google 的 V8 引擎。這兩個引擎處理程式碼的方式不同。
JavaScriptCore 執行一系列步驟來解釋和最佳化腳本:
它執行詞法分析,將原始程式碼分解為一系列標記或具有已識別含義的字串。
然後解析器會分析標記的語法並建構到語法樹。
然後啟動四個 JIT(即時)進程,分析並執行解析器產生的字節碼。
簡單來說,這個JavaScript 引擎取得您的原始程式碼,將其分解為字串(也稱為詞法分析),取得這些字串並將它們轉換為編譯器可以理解的字節碼,然後執行它。
Google 的 V8 引擎用 C 語言編寫,也編譯和執行 JavaScript 原始碼、處理記憶體分配以及垃圾收集剩餘部分。它的設計由一個編譯器管道組成,可將原始程式碼直接編譯為機器碼:
Ignition,產生字節碼的解釋器
TurboFan,一種最佳化編譯器,可將位元組碼編譯為機器碼
SparkPlug,一個補充 TurboFan 的編譯器
如果您對歷史感興趣,這個新管道取代了 V8 之前使用的較舊的 Full-codegen 和 Crankshaft 雙編譯器設計。
編譯過程產生機器碼後,引擎會將ECMA 標準中指定的所有資料類型、運算子、物件和函數公開給瀏覽器或任何需要使用它們的執行時間,例如Node.js, Deno 或Electron(由Visual Studio Code 使用)。
如果 JavaScript 引擎在後台悄悄運行,解析程式碼並將其分解為可讀字串,以便編譯器可以讀取和編譯它,那麼運行時往往會吸引更多關注。這是為什麼?
眾所周知的運行時在 JavaScript 引擎之上工作,擴展了它們的功能。最知名的是 Node,但 Deno 和 Bun 是這個領域的新人。 Node 和 Deno 嵌入了 V8,Bun 嵌入了 JavaScriptCore。
Bun 聲稱比 Node 或 Deno 運行得更快,因為 JavaScriptCore 比 V8 更快,每秒處理 69,845 個 http 請求,而 Node 為 16,288 個,Deno 為 12,926 個。
正如Bun 的文檔所述,這些運行時的目標是「在瀏覽器之外運行世界上大部分JavaScript,為未來的基礎設施帶來效能和複雜性增強,並透過更好、更簡單的工具提高開發人員的生產力。
NativeScript 是專門為使用 JavaScript 建置的跨平臺本機行動應用程式開發而建置的執行時間的一個很好的範例。
這些運行時也是為了解決 JavaScript 單執行緒架構帶來的一些固有問題而建構的。例如,Node 優先考慮例程的非同步、無執行緒執行。所有這些運行時都提供了精心策劃的開發人員體驗,包括對深受喜愛的 API(如 fetch、websocket,甚至是 React 開發人員喜愛的 JSX)的內建支援。這可能是它們容易吸引開發者註意的原因。
整體而言,執行階段解決了標準瀏覽器架構及其驅動引擎的效能差距。隨著引擎的發展,這些運行時肯定也會發展。
有多種 JavaScript 引擎可用於分析、解析和執行客戶端程式碼。隨著每個瀏覽器版本的發布,JavaScript 引擎可能會發生變更或最佳化,以跟上 JavaScript 程式碼執行的最新技術水平。
在被這些引擎的名稱完全混淆之前,請記住,大量的行銷活動都投入到了這些引擎及其背後的瀏覽器中,這是很有用的。在這篇對JavaScript 編譯的有用分析中,作者諷刺地指出:「如果你不知道,編譯器大約37% 是由行銷組成的,而品牌重塑是你可以對編譯器做的為數不多的事情之一,從行銷角度來看,因此列車名稱為:SquirrelFish、Nitro、SFX...」
在牢記命名和重命名這些引擎的起起落落的同時,注意 JavaScript 引擎歷史上的一些重大事件也是很有用的。我為您整理了一個方便的圖表:
Browser, Headless Browser, or Runtime | JavaScript Engine |
---|---|
Mozilla | Spidermonkey |
Chrome | V8 |
IE | Chakra |
Safari | JavaScriptCore* |
Node.js | V8 |
Deno | V8 |
Bun | JavaScriptCore |
Edge** | Blink and V8 |
*JavaScriptCore 重寫為 SquirrelFish,更名為 SquirrelFish Extreme,也稱為 Nitro。然而,將 JavaScriptCore 稱為 WebKit 實作(例如 Safari)底層的 JavaScript 引擎仍然是正確的說法。
**Edge 最初使用 Chakra 引擎,其中部分引擎被微軟開源。然後,Edge 被重建為 Chromium 瀏覽器,底層則有 Blink 和 V8 JavaScript 引擎。
JavaScript 引擎的程式碼解析和執行過程的目標是在最短的時間內產生最優化的程式碼。
最重要的是,這些引擎的發展與我們對發展網路和行動環境以使其盡可能高效能的追求是並行的。要追蹤這一演變,您可以在基準測試圖表中查看各種引擎的表現,例如 arewefastyet.com 上產生的圖表。
任何 Web 開發人員都需要了解瀏覽器中固有的差異,這些瀏覽器顯示我們努力產生、偵錯和維護的程式碼。為什麼某些腳本在一種瀏覽器上運行緩慢,但在另一種瀏覽器上運行速度更快?
類似地,行動開發人員,尤其是那些使用 webview 來顯示其內容編寫混合行動應用程式的開發人員,會想知道哪些引擎正在解釋他們的 JavaScript 程式碼。所有關心使用者體驗的 Web 開發人員都應該了解小型裝置上各種瀏覽器固有的限制和提供的可能性。跟上
的變化
隨著您成為 Web、行動或應用程式開發人員,JavaScript 引擎將是值得花時間的。
本文最初於 2015 年出現在 Telerik 開發者網路上,此後已針對 2022 年及以後進行了修訂和更新。維基百科的 JavaScript 引擎條目中引用了原始文章。
以上是什麼是 JavaScript 引擎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!