JavaScript️可視化:js引擎

今天我們來聊聊js引擎

JavaScript很酷,但是機器如何才能真正理解您編寫的代碼?作為JavaScript開發人員,我們通常不必自己處理編譯器。但是,一定要了解JavaScript引擎的基礎知識,看看它如何處理我們人類友好的JS代碼,並將其轉變為機器可以理解的東西!

|注意: 實現基於Node.js和基於Chromium的瀏覽器使用的V8引擎。

HTML解析器遇到script帶有源的標記。來自script的代碼從網絡,緩存或已安裝的service worker中加載。請求腳本作為一個字節流被響應,該字節流被字節流解碼器處理!字節流解碼器對字節流進行解碼,一旦它被下載。

JavaScript️可視化:js引擎

字節流解碼器從解碼的字節流中創建token。例如,0066解碼為f, 0075解碼為u, 006e解碼為n,0063解碼為c, 0074解碼為t,0069解碼為i, 006f解碼為o和 006e解碼為n後跟一個空格。好像你寫function一樣!這是JavaScript中的保留關鍵字,創建token並將其發送到解析器(和pre-parser,我沒有在gif中介紹,但稍後會進行解釋)。其餘字節流也會發生同樣的情況。

JavaScript️可視化:js引擎

引擎使用兩個解析器:預解析器和解析器。預解析器僅及早檢查token,以查看是否存在語法錯誤❌。這樣可以減少發現代碼中錯誤的數量,否則解析器稍後會發現錯誤!

如果沒有錯誤,則解析器根據從字節流解碼器接收的token創建節點。使用這些節點,它會創建一個抽象語法樹或AST。

JavaScript️可視化:js引擎

接下來,是時候翻譯了!翻譯器(interpreter)遍歷AST,並根據AST包含的信息生成字節碼。字節代碼生成完畢後,將刪除AST,以清除內存空間。最後,我們有一些機器可以使用的東西!

JavaScript️可視化:js引擎

儘管字節碼很快,但是可以更快。運行此字節碼時,將生成信息。它可以檢測某些行為是否經常發生,以及所使用的數據類型。也許您已經調用了數十次函數:是時候對其進行優化,使其運行得更快了!♀‍♀️

字節碼與生成的類型反饋一起被髮送到優化編譯器(optimizing compiler)。優化編譯器獲取字節碼和類型反饋,並從中生成高度優化的機器碼。

JavaScript️可視化:js引擎

JavaScript是一種動態類型化的語言,這意味著數據類型可以不斷變化。如果JavaScript引擎每次必須檢查某個值具有哪種數據類型,那將非常慢。

相反,引擎使用一種稱為內聯緩存(inline caching)的技術。它將代碼緩存在內存中,以期將來返回具有相同行為的相同值!假設某個函數被調用了100次,並且到目前為止一直返回相同的值。它將假定它也會在您第101次調用它時返回該值。

假設我們有以下函數sum,到目前為止,每次都使用數值作為參數來調用它:

JavaScript️可視化:js引擎

這將返回數字3!下次調用它時,它將假定我們再次使用兩個數值調用它。

如果是這樣,則不需要動態查找,它可以使用存儲在已引用的特定內存插槽中的結果。否則,如果假設不正確,它將不會對代碼進行優化,並且恢復為原始字節代碼,而不是優化後的機器代碼。

例如,下一次調用它時,我們傳遞的是字符串而不是數字。由於JavaScript是動態類型的,因此我們可以做到這一點而沒有任何錯誤!

JavaScript️可視化:js引擎

這意味著該數字2將被強制轉換為字符串,而該函數將返回該字符串 "12"。返回執行解釋的字節碼並更新類型反饋。

希望這篇文章對您有用!當然,我在這篇文章中沒有涉及引擎的許多部分(JS堆,調用堆棧等),如果您對JavaScript的內部結構感興趣,我絕對鼓勵您自己開始做一些研究,V8是開源的,並且有一些很好的文檔說明了它的幕後工作方式!


分享到:


相關文章: