JavaScript程式碼是怎麼在瀏覽器裡面運行起來的?
JavaScript程式碼是怎麼在瀏覽器裡面運行的?下面簡單探索一下
瀏覽器內核
瀏覽器內核(Rendering Engine
),常見的叫法如:排版引擎、解釋引擎、渲染引擎,現在流行稱為瀏覽器內核。
瀏覽器 | 內核 | 說明 |
---|---|---|
IE | Trident | IE、獵豹安全、360極速瀏覽器、百度瀏覽器 |
FireFox | Gecko | 可惜這幾年已經沒落了,打開速度慢、升級頻繁、豬一樣的隊友flash、神一樣的對手chrome。 |
Safari | Webkit | 從Safari推出之時起,它的渲染引擎就是Webkit,一提到 webkit,首先想到的便是 chrome,可以說,chrome 將 Webkit內核 深入人心,殊不知,Webkit 的鼻祖其實是 Safari。 |
Chrome | Chromium/Blink | 在 Chromium 項目中研發 Blink 渲染引擎(即瀏覽器核心),內置於 Chrome 瀏覽器之中。Blink 其實是 WebKit 的分支。大部分國產瀏覽器最新版都採用Blink內核。二次開發 |
Opera | Blink |
瀏覽器渲染過程
-
HTML
首先會被瀏覽器內核中的HTML Parser
解析,最終會構建成一顆DOM樹。 -
CSS
會被瀏覽器內核中的CSS Parser
解析,形成CSS規則,CSS規則和DOM樹結合形成一個渲染樹,通過layout(布局)生成最終的渲染樹。
為什麼要有
layout
呢?因為要適配不同尺寸的螢幕。有了渲染樹之後就可以繪製展現出來了。
常見的js引擎
-
SpiderMonkey:第一款js引擎,由Brendan Eich開發(js作者)。
-
Chakra:微軟開發,由於IE瀏覽器。
-
JavascriptCore:webkit的js引擎,Apple公司開發。
-
V8:Google開發的強大js引擎,也幫助Chrome從眾多瀏覽器中脫穎而出。
瀏覽器內核和js引擎的關係
這裡用webkit為列,webkit最重要的兩部分:
WebCore
: 負責HTML、CSS的解析、布局、渲染等相關工作;JavascriptCore
:解析、執行js程式碼。
下面是Chromium的架構圖
普通JavaScript引擎(笨重)
作用:javascript引擎幫助我們將js程式碼編譯成CPU認識的指令集,最終被cpu執行。
普通JavaScript引擎除了編譯之外還要負責執行以及記憶體管理。 js是解釋形語言,由引擎直接讀取源碼,一邊編譯一邊執行,這樣效率相對較低,而編譯形語言(如c++)是把源碼直接編譯成可直接執行的程式碼執行效率更高。
隨著技術的發展,對JavaScript性能的要求越來越高,V8引擎就是在此背景下產生的,它產生的目的就是為了提高javascript執行的性能。
V8引擎(輕量)
V8引擎是一個JavaScript引擎實現,最初由一些語言方面專家設計,後被Google收購,隨後Google對其進行了開源。
V8使用C++開發,在運行JavaScript之前,相比其它的JavaScript的引擎轉換成位元組碼或解釋執行,V8將其編譯成原生機器碼(IA-32, x86-64, ARM, or MIPS CPUs),並且使用了如內聯快取(inline caching)等方法來提高性能。
將javascript程式碼轉換成AST
V8引擎會先將javascript程式碼轉換成AST(抽象語法樹),事實上所有的程式語言都會將源程式碼解析成抽象語法樹(abstract syntax tree, AST)。
AST是電腦科學中很早的一個概念,不是V8特有的(只是V8在轉換過程中做了非常多的優化),更不是javascript特有的。
AST的用途
AST的作用也不僅僅是用來在V8的編譯上,比如我們常用的babel插件將 es6->es5 、ts->js 、死區分析、Dead Code、編譯壓縮打包、css預處理器、eslint等等,這些功能的實現都離不開AST。
AST編譯過程
V8執行js的簡易流程
-
瀏覽器內核將源碼以流的方式交給v8引擎,v8引擎獲取到源碼並進行編碼轉換
-
詞法分析Scanner,將程式碼轉成tokens
-
語法分析Parser、Preparser,直接將tokens轉換成AST樹結構
-
位元組碼生成
parser就是直接將tokens轉換成AST樹結構
preParse稱之為預解析,為什麼需要預解析呢?
這是因為並不是所有的js程式碼一開始就會被執行,如果對所有的js程式碼都進行解析,會影響網頁運行效率。所以v8引擎就實現了延遲解析的方案,將不必要的函數進行預解析,也就是只解析暫時需要的內容,而對函數的全量解析是在函數被調用時才會進行
比如我們在一個函數outer內部定義了另外一個函數inner,那麼inner函數就會進行預解析
下面看一下在線解析AST的示例👇
瀏覽器內核與JS引擎本篇就簡單聊這麼多,先淺淺的了解一下。關於V8的東西很多,也有很多非常絕妙的設計,更多V8相關的戳這裡,一步步解鎖吧!
我是 甜點cc☭
微信公眾號:【看見另一種可能】
熱愛前端開發,也喜歡專研各種跟本職工作關係不大的技術,技術、產品興趣廣泛且濃厚。本號主要致力於分享個人經驗總結,希望可以給一小部分人一些微小幫助。
希望能和大家一起努力營造一個良好的學習氛圍,為了個人和家庭、為了中國的互聯網物聯網技術、數字化轉型、數字經濟發展做一點點貢獻。數風流人物還看中國、看今朝、看你我。