
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.歡迎大家進群交流讨論,學習交流,共同進步。
當真正開始學習的時候難免不知道從哪入手,導緻效率低下影響繼續學習的信心。
但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,是以有有效資源還是很有必要的。
最後祝福所有遇到瓶疾且不知道怎麼辦的前端程式員們,祝福大家在往後的工作與面試中一切順利。