【動畫演示】JavaScript 引擎運行原理

做者:Lydia Halliejavascript

譯者:前端小智前端

來源: devjava

點贊再看,養成習慣
git


本文 GitHub:github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。github

JavaScript 很酷,可是 JS 引擎是如何才能理解咱們編寫的代碼呢?做爲 JS 開發人員,咱們一般不須要本身處理編譯器。然而,瞭解 JS 引擎的基礎知識並瞭解它如何處理JS代碼,並將其轉換成機器可以理解的東西,絕對是個有益無害的事情。面試

注意:本文主要基於 Node.js 和基於 Chrome 的瀏覽器使用的 V8 引擎。瀏覽器

HTML解析器遇到帶有源代碼的script標籤。 來自此源的代碼從網絡,緩存或已安裝的服務工做程序中加載。 響應是將請求的腳本做爲字節流,由字節流解碼器負責。字節流解碼器在下載字節流時對其進行解碼。緩存

字節流解碼器從已解碼的字節流中建立令牌。例如,0066解碼爲f, 0075u, 006en, 0063c, 0074t, 0069i, 006fo, 006en,後面跟一個空格。就像JS中的function,這是 JS 中的一個保留關鍵字,它會建立一個標記,並將其發送給解析器。對於字節流的其他部分也是如此。bash

該引擎使用兩個解析器:預解析器(pre-parser)解析器(parser)。預解析器只提早檢查標記,以查看是否有語法錯誤。這能夠減小發現代碼中的錯誤所需的時間,不然解析器稍後就會發現這些錯誤。網絡

若是沒有錯誤,解析器將根據從字節流解碼器接收到的標記建立節點。使用這些節點,它建立了一個抽象語法樹,即AST

接下來,輪到解釋器(interpreter)了。遍歷AST並根據AST包含的信息生成字節碼的解釋器。一旦字節碼徹底生成,AST就會被刪除,從而清除內存空間。最後,生成的機器碼就能夠在電腦上運行了。

雖然字節碼很快,但它能夠更快。當這個字節碼運行時,將生成信息。它能夠檢測某些行爲是否常常發生,以及所使用數據的類型。也許已經調用一個函數幾十次了:如今是時候優化它了,這樣它會運行得更快!

字節碼與生成的類型反饋一塊兒發送到優化編譯器(ptimizing compiler)。 優化的編譯器接收字節碼和類型反饋,並根據這些信息生成高度優化的機器碼。

JS 是一種動態類型語言,這意味着數據類型能夠不斷變化。若是 JS引擎每次都要檢查某個值的數據類型,那麼速度會很是慢。

相反,JS 引擎使用一種稱爲**內聯緩存(inline caching)**的技術。它將代碼緩存在內存中,但願未來它會以相同的行爲返回相同的值.假設某個函數被調用100次,而且到目前爲止老是返回相同的值。它將假設在第101次調用它時也會返回這個值。

假設咱們有如下函數sum,(到目前爲止)每次都使用數值做爲參數來調用它:

function sum(a, b) {
    return a + b
}
sum(1,2)
複製代碼

執行結果爲 3。 下次調用它時,它將假定咱們再次使用兩個相同數字對其進行調用。

若是假投,那麼就不須要動態查找,只須要使用存儲在特定內存槽中的結果,該槽已經有一個引用。不然,若是假設不正確,它將反優化代碼並恢復到原始字節碼,而不是優化後的機器碼。

例如,下一次調用它時,咱們傳遞的是字符串而不是數字。由於 JS 是動態類型的,因此這樣作不會有任何錯誤。

function sum(a, b) {
    return a + b
}
sum('1',2)
複製代碼

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

我但願這篇文章對你有用!固然,在這篇文章中尚未涉及到引擎的更多部分(JS堆,調用堆棧,等等),後續會繼續分享。若是你對 JS 的內部機制感興趣,強烈建議本身能夠作一些研究,V8 是開源的,而且有一些很棒的文檔說明它是如何工做的。


dev.to/lydiahallie…

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug


交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

github.com/qq449245884…

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索