天天看點

javascript引擎工作原理

javascript引擎工作原理

1. 什麼是JavaScript解析引擎?

簡單地說,JavaScript解析引擎就是能夠“讀懂”JavaScript代碼,并準确地給出代碼運作結果的一段程式。比方說,當你寫了 var a = 1 + 1; 這樣一段代碼,JavaScript引擎做的事情就是看懂(解析)你這段代碼,并且将a的值變為2。

學過編譯原理的人都知道,對于靜态語言來說(如Java、C++、C),處理上述這些事情的叫編譯器(Compiler),相應地對于JavaScript這樣的動态語言則叫解釋器(Interpreter)。這兩者的差別用一句話來概括就是:編譯器是将源代碼編譯為另外一種代碼(比如機器碼,或者位元組碼),而解釋器是直接解析并将代碼運作結果輸出。 比方說,firebug的console就是一個JavaScript的解釋器。

但是,現在很難去界定說,JavaScript引擎它到底算是個解釋器還是個編譯器,因為,比如像V8(Chrome的JS引擎),它其實為了提高 JS的運作性能,在運作之前會先将JS編譯為本地的機器碼(native machine code),然後再去執行機器碼(這樣速度就快很多),相信大家對JIT(Just In Time Compilation)一定不陌生吧。

我個人認為,不需要過分去強調JavaScript解析引擎到底是什麼,了解它究竟做了什麼事情我個人認為就可以了。對于編譯器或者解釋器究竟是如何看懂代碼的,翻出大學編譯課的教材就可以了。

這裡還要強調的就是,JavaScript引擎本身也是程式,代碼編寫而成。比如V8就是用C/C++寫的。

2. JavaScript解析引擎與ECMAScript是什麼關系?

JavaScript引擎是一段程式,我們寫的JavaScript代碼也是程式,如何讓程式去讀懂程式呢?這就需要定義規則。比如,之前提到的var a = 1 + 1;,它表示:

  • 左邊var代表了這是申明(declaration),它申明了a這個變量
  • 右邊的+表示要将1和1做加法
  • 中間的等号表示了這是個指派語句
  • 最後的分号表示這句語句結束了

上述這些就是規則,有了它就等于有了衡量的标準,JavaScript引擎就可以根據這個标準去解析JavaScript代碼了。那麼這裡的 ECMAScript就是定義了這些規則。其中ECMAScript 262這份文檔,就是對JavaScript這門語言定義了一整套完整的标準。其中包括:

  • var,if,else,break,continue等是JavaScript的關鍵詞
  • abstract,int,long等是JavaScript保留詞
  • 怎麼樣算是數字、怎麼樣算是字元串等等
  • 定義了操作符(+,-,>,<等)
  • 定義了JavaScript的文法
  • 定義了對表達式,語句等标準的處理算法,比如遇到==該如何處理
  • ⋯⋯

标準的JavaScript引擎就會根據這套文檔去實作,注意這裡強調了标準,因為也有不按照标準來實作的,比如IE的JS引擎。這也是為什麼JavaScript會有相容性的問題。至于為什麼IE的JS引擎不按照标準來實作,就要說到浏覽器大戰了,這裡就不贅述了,自行Google之。

是以,簡單的說,ECMAScript定義了語言的标準,JavaScript引擎根據它來實作,這就是兩者的關系。

3. JavaScript解析引擎與浏覽器又是什麼關系?

簡單地說,JavaScript引擎是浏覽器的組成部分之一。因為浏覽器還要做很多别的事情,比如解析頁面、渲染頁面、Cookie管理、曆史記錄 等等。那麼,既然是組成部分,是以一般情況下JavaScript引擎都是浏覽器開發商自行開發的。比如:IE9的Chakra、Firefox的 TraceMonkey、Chrome的V8等等。

進而也看出,不同浏覽器都采用了不同的JavaScript引擎。是以,我們隻能說要深入了解哪個JavaScript引擎。

4. 深入了解其内部原理的途徑有哪些?

搞清楚了前面三個問題,那這個問題就好回答了。個人認為,主要途徑有如下幾種(依次由淺入深):

​看講JavaScript引擎工作原理的書​

這種方式最友善,不過我個人了解到的這樣的書幾乎沒有,但是Dmitry A.Soshnikov​部落格上的文章真的是非常的贊,建議直接看英文,實在英文看起來吃力的,可以看譯本

​看ECMAScript的标準文檔​

這種方式相對直接,原汁原味,因為引擎就是根據标準來實作的。目前來說,可以看第五版​和第三版,不過要看懂也是不容易的。

​看JS引擎源代碼​

這種方式最直接,當然也最難了。因為還牽涉到了如何實作詞法分析器,文法分析器等等更加底層的東西了,而且并非所有的引擎代碼都是開源的。

5. 以上幾種方式中第一種都很難看明白怎麼辦?

其實第一種方式中的文章,作者已經将文檔中内容提煉出來,用通俗易懂的方式闡述出來了。如果,看起來還覺得吃力,那說明還缺少兩塊的東西:

​對JavaScript本身還了解的不夠深入​

如果你剛剛接觸JavaScript,或者說以前甚至都沒有接觸過。那一下子就想要去了解内部工作原理,的确是很吃力的。首先應該多看看書,多實踐實踐,從知識和實踐的方式來了解JavaScript預言特性。這種情況下,你隻需要了解現象。比方說,(function(){})() 這樣可以直接調用該匿名函數、用閉包可以解決循環中的延遲操作的變量值擷取問題等等。要了解這些,都是需要多汲取和實踐的。實踐這裡就不多說了,而知識汲取方面可以多看看書和部落格。這個層面的書就相對比較多了,《Professional JavaScript for Web Developers》就是本很好的書(中文版請自行尋找)。

​缺乏相應的領域知識​

當JavaScript也達到一定深度了,但是,還是看不大明白,或者沒法很深入到内部去一探究竟。那就意味着缺少對 應的領域知識。這裡明顯的就是編譯原理相關的知識。不過,其實對這塊了解個大概基本看起來就沒問題了。要再繼續深入,那需要對編譯原理了解的很深入,比如 說詞法分析采用什麼算法,一般怎麼處理。會有什麼問題,如何解決,AST生成算法一般有哪幾種等等。那要看編譯原理方面的書,也有基本經典的書,比如《Compilers: Principles, Techniques, and Tools》​這本也是傳說中的龍書,還有非常著名的《SICP》​和《PLAI》。 不過其實根據個人經驗,對于Dmitry的文章,要看懂它,隻要你對JavaScript有一定深度的了解,同時你大學計算機的課程都能大緻掌握了(尤其 是作業系統),也就是說基礎不錯,了解起來應該沒問題。因為這些文章基本沒有涉及底層編譯相關的,隻是在解釋文檔的内容,并且其中很多東西都是相通的,比 如:context的切換與CPU的程序切換、函數相關的的局部變量的棧存儲、函數退出的操作等等都是一緻的。

​最後​

為了幫助大家讓學習變得輕松、高效,給大家免費分享一大批資料,幫助大家在成為全棧工程師,乃至架構師的路上披荊斬棘。在這裡給大家推薦一個前端全棧學習交流圈:​866109386​.歡迎大家進群交流讨論,學習交流,共同進步。

當真正開始學習的時候難免不知道從哪入手,導緻效率低下影響繼續學習的信心。

但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,是以有有效資源還是很有必要的。

最後祝福所有遇到瓶疾且不知道怎麼辦的前端程式員們,祝福大家在往後的工作與面試中一切順利。

繼續閱讀