新聞中心
有時(shí)編寫 Web 應(yīng)用的代碼會(huì)感覺充滿魔力,因?yàn)槲覀冎皇菍懥艘幌盗凶址?,就能在瀏覽器里看到效果了。但是理解魔法背后的技術(shù),可以幫助你更好地提高編程技巧。至少當(dāng)你試 圖解釋在 JavaScript 驅(qū)動(dòng)的 web 或移動(dòng)應(yīng)用的幕后發(fā)生了什么的時(shí)候,會(huì)覺得自己不那么白癡了。

很多年前,那是我還是個(gè)研究生講師,向一個(gè)教授抱怨還沒有掌握那些特別難懂的法語語法點(diǎn),可以教給我的本科學(xué)生。我記得當(dāng)時(shí)她說的話:“有時(shí)候,學(xué)習(xí)某個(gè)事物的唯一方式就是教授它?!?/p>
嘗試向工程師解釋 NativeScript 是如何通過 JavaScript 引擎在幕后工作、 在運(yùn)行時(shí)連接調(diào)用原生的 APIs——面對這樣一件復(fù)雜的工作很容易在一片雜草中迷失方向。事實(shí)上,任何 JavaScript 開發(fā)者都應(yīng)該對我們每天使用的這門技術(shù)基礎(chǔ)的引擎感到好奇。現(xiàn)在我們一起來仔細(xì)分析下 JavaScript 引擎到底做了什么,為什么不同的平臺使用不同引擎,多年來它們是如何發(fā)展的,以及作為開發(fā)者我們?yōu)槭裁匆P(guān)注這些。
首先,一些專業(yè)術(shù)語
“JavaScript 引擎”通常被稱作一種 虛擬機(jī)?!疤摂M機(jī)”是指軟件驅(qū)動(dòng)的給定的計(jì)算機(jī)系統(tǒng)的模擬器。有很多類型的虛擬機(jī),它們根據(jù)自己在多大程度上精確地模擬或代替真實(shí)的物理機(jī)器來分類。
例如,“系統(tǒng)虛擬機(jī)”提供了一個(gè)可以運(yùn)行操作系統(tǒng)的完整仿真平臺。Mac 用戶很熟悉的 Parallels 就是一個(gè)允許你在 Mac 上運(yùn)行 Windows系統(tǒng)虛擬機(jī)。
另一方面,“進(jìn)程虛擬機(jī)”不具備全部的功能,能運(yùn)行一個(gè)程序或者進(jìn)程。Wine 是一個(gè)允許你在 Linux 機(jī)器上運(yùn)行 Windows 應(yīng)用的進(jìn)程虛擬機(jī),但是并不在 Linux 中提供完整的 Windows 操作系統(tǒng)。
JavaScript 虛擬機(jī)是一種進(jìn)程虛擬機(jī),專門設(shè)計(jì)來解釋和執(zhí)行的 JavaScript 代碼。
注意:要區(qū)別在瀏覽器中排布頁面布局的 布局引擎 和解釋和執(zhí)行代碼的底層 JavaScript 引擎是非常重要的。在 這里 可以找到一個(gè)很好的闡釋。
那么,確切來講,到底什么是 JavaScript 引擎,它做了什么?
JavaScript 引擎的基本工作是把開發(fā)人員寫的 JavaScript 代碼轉(zhuǎn)換成高效、優(yōu)化的代碼,這樣就可以通過瀏覽器進(jìn)行解釋甚至嵌入到應(yīng)用中。事實(shí)上,JavaScriptCore 自稱為“優(yōu)化虛擬機(jī)”。
更準(zhǔn)確地講,每個(gè) JavaScript 引擎都實(shí)現(xiàn)了一個(gè)版本的 ECMAScript,JavaScript 是它的一個(gè)分支。隨著 ECMAScript 的不斷發(fā)展,JavaScript 引擎也不斷改進(jìn)。之所以有這么多不同的引擎,是因?yàn)樗鼈兠總€(gè)都被設(shè)計(jì)運(yùn)行在不同的 web 瀏覽器、headless 瀏覽器、或者像 Node.js 那樣的運(yùn)行時(shí)環(huán)境中。
你也許熟悉 web 瀏覽器,那什么是 headless 瀏覽器呢?它是一個(gè)沒有圖形用戶界面的 web 瀏覽器。它們在對 web 產(chǎn)品進(jìn)行自動(dòng)化測試時(shí)十分有用。一個(gè)很棒的例子就是 PhantomJS。那 Node.js 又和 JavaScript 引擎有什么關(guān)系?Node.js 是一個(gè)異步的、事件驅(qū)動(dòng)的框架,讓你在服務(wù)器端可以使用 JavaScript。既然他們是驅(qū)動(dòng) JavaScript 的工具,所以它們也是由 JavaScript 引擎驅(qū)動(dòng)。
按照上述關(guān)于虛擬機(jī)的定義,把 JavaScript 引擎稱作進(jìn)程虛擬機(jī)就很好理解了,因?yàn)樗奈ㄒ坏哪康木褪亲x取和編譯 JavaScript 代碼。這并不意味著它只是個(gè)簡單的引擎。比如,JavaScriptCore 就有六個(gè)“構(gòu)建模塊”可以分析、解釋、優(yōu)化、垃圾回收 JavaScript 代碼。
它是如何工作的?
當(dāng)然,這決定于引擎。吸引我們注意的兩個(gè)主要的引擎都利用了 NativeScript ,它們分別是 WebKit 的 JavaScriptCore 和 Google 的 V8 引擎。這兩個(gè)引擎使用不同的方式處理代碼。
JavaScriptCore 執(zhí)行 一系列步驟 來解釋和優(yōu)化腳本:
-
它進(jìn)行詞法分析,就是將源代碼分解成一系列具有明確含義的符號或字符串。
-
然后用語法分析器分析這些符號,將其構(gòu)建成語法樹。
-
接著四個(gè) JIT(Just-In-Time)進(jìn)程開始參與進(jìn)來,分析和執(zhí)行解析器所生成的字節(jié)碼。
什么?簡單來說,JavaScript 引擎會(huì)加載你的源代碼,把它分解成字符串(又叫做分詞),再 把這些字符串轉(zhuǎn)換 成編譯器可以理解的字節(jié)碼,然后執(zhí)行這些字節(jié)碼。
Google 的 V8 引擎 是用 C++ 編寫的,它也能夠編譯并執(zhí)行 JavaScript 源代碼、處理內(nèi)存分配和垃圾回收。它被設(shè)計(jì)成由兩個(gè)編譯器組成,可以把源碼直接編譯成機(jī)器碼:
-
Full-codegen:輸出未優(yōu)化代碼的快速編譯器
-
Crankshaft: 輸出執(zhí)行效率高、優(yōu)化過的代碼的慢速編譯器
如果 Crankshaft 確定需要優(yōu)化的代碼是由 Full-codegen 生成的未優(yōu)化代碼,它就會(huì)取代 Full-codegen,這個(gè)過程叫做“crankshafting”。
一旦編譯過程中產(chǎn)生了機(jī)器代碼,引擎就會(huì)向?yàn)g覽器暴露所有的數(shù)據(jù)類型、操作符、對象、在 ECMA 標(biāo)準(zhǔn)中指定的函數(shù)、或任何運(yùn)行時(shí)需要使用的東西,NativeScript 就是如此。
有哪些 JavaScript 引擎?
有一大堆令人眼花繚亂的 JavaScript 引擎可以用來解釋、分析和執(zhí)行你的客戶端代碼。每個(gè)瀏覽器版本發(fā)布時(shí),它的 JavaScript 引擎都可能有所改變或優(yōu)化以跟上 JavaScript 代碼執(zhí)行技術(shù)的狀況的變化。
你還沒被這些瀏覽器引擎的名字完全弄糊涂之前,請記住很多市場營銷的元素被加入了這些引擎和以它們?yōu)榛A(chǔ)的瀏覽器。這篇對 JavaScript 編譯 十分有用的分析 中,作者諷刺地指出:“你所不知道的是,編譯器大約有 37% 是由市場營銷構(gòu)成的,對編譯器進(jìn)行品牌重塑也是你能做的為數(shù)不多的事情之一,智慧的市場營銷,故而有了一系列名字:SquirrelFish、Nitro、SFX……”。
在牢記營銷對命名和重命名這些引擎的影響的同時(shí),注意到幾件在 JavaScript 引擎發(fā)展史上的重大事件是很有用的。我為你做了一個(gè)便于理解的圖表:
|
Browser, Headless Browser, or Runtime |
JavaScript Engine |
|---|---|
Mozilla |
Spidermonkey |
Chrome |
V8 |
Safari |
JavaScriptCore |
IE and Edge |
Chakra |
PhantomJS |
JavaScriptCore |
HTMLUnit |
Rhino |
TrifleJS |
V8 |
Node.js |
V8 |
Io.js* |
V8 |
*JavaScriptCore 被改寫為 SquirrelFish,升級版本為 QuirrelFish Extreme,也叫做 Nitro。然而,構(gòu)成 Webkit 實(shí)現(xiàn)基礎(chǔ)的 JavaScript 引擎就是 JavaScriptCore(比如 Safari)。
**iOS 開發(fā)者應(yīng)該要知道移動(dòng)設(shè)備的 Safari 使用 Nitro,但是 UIWebView 不包括 JIT 編譯,所以體驗(yàn)會(huì)慢一些。然而開發(fā)人員可以在 iOS8 中使用包含 Nitro 的 WKWebView,使用體驗(yàn) 明顯 變快?;旌弦苿?dòng)應(yīng)用程序的開發(fā)人員應(yīng)該能松口氣了。
*最終 io.js 從 Node.js 分離開的原因之一就是為了支持 V8 版本的引擎。這仍然是一個(gè)挑戰(zhàn),正如 這里 講述的。
我們?yōu)槭裁匆P(guān)注?
JavaScript 引擎的代碼解析和執(zhí)行過程的目標(biāo)就是在最短時(shí)間內(nèi)編譯出***化的代碼。
最重要的是,這些引擎的演進(jìn)與我們對發(fā)展 web 和 移動(dòng)平臺的不斷探究息息相關(guān),讓它們盡可能具有高性能,是相輔相成的。為了追蹤這種演進(jìn),你可以看到各種各樣的引擎在基準(zhǔn)圖中是如何表現(xiàn)的,就好像 arewefastyet.com 總結(jié)的。例如,比較 Chrome 在搭載 V8 引擎與 non-Crankshafted 引擎時(shí)的表現(xiàn)就很有趣。
任何一個(gè) web 開發(fā)者都要意識到,我們努力編寫、調(diào)試和維護(hù)的代碼在不同瀏覽器中執(zhí)行效果必然有所差異。為什么某段代碼在一個(gè)瀏覽器上工作得很慢,但在另一個(gè)上卻快得多?
同樣地,移動(dòng)開發(fā)者,尤其是使用 webview 顯示頁面內(nèi)容的混合移動(dòng)應(yīng)用開發(fā)者,或者那些使用像 NativeScript 這種運(yùn)行時(shí)環(huán)境的開發(fā)者,想知道是什么引擎在解釋執(zhí)行他們的 JavaScript 代碼。移動(dòng) web 開發(fā)者應(yīng)該注意到那些小小設(shè)備上的瀏覽器所具備的各種局限性和可能性。作為一個(gè)想持續(xù)發(fā)展的 web、移動(dòng)或應(yīng)用程序開發(fā)人員,時(shí)刻關(guān)注 JavaScript 引擎的變化會(huì)帶給你超值回報(bào)。
文章名稱:一篇給小白看的JavaScript引擎指南
網(wǎng)頁網(wǎng)址:http://m.5511xx.com/article/djsggdd.html


咨詢
建站咨詢
