1. 程式人生 > >如何去了解JavaScript引擎的工作原理 js:我們應該如何去了解JavaScript引擎的工作原理(轉)

如何去了解JavaScript引擎的工作原理 js:我們應該如何去了解JavaScript引擎的工作原理(轉)

js:我們應該如何去了解JavaScript引擎的工作原理(轉)

http://www.nowamagic.net/librarys/veda/detail/1579

昨天收到一封來自深圳的一位前端童鞋的郵件,郵件內容如下(很抱歉,未經過他的允許,公開郵件內容,不過我相信其他人肯定也有同樣的問題,所以,直接把問題原文丟擲來):

“讀了你的幾篇關於JS(變數物件、作用域、上下文、執行程式碼)的文章,我個人覺得有點抽象,難以深刻理解。我想請教下通過什麼途徑能夠深入點的瞭解javascript解析引擎在執行程式碼前後是怎麼工作的,ecma英文版實在看不下去呵呵。”

其實這個問題個人覺得太籠統了,直接回答很難回答,所以,我打算先把他的問題拆解成如下幾個子問題,並對其表達個人的觀點,希望對有同樣困惑的童鞋能夠有所幫助。

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的語法
  • 定義了對錶達式,語句等標準的處理演算法,比如遇到==該如何處理
  • ⋯⋯

注:js相容性問題的原因

標準的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的程序切換、函式相關的的區域性變數的棧儲存、函式退出的操作等等都是一致的。

以上就是個人對這個問題的看法,除此之外,我覺得,學習任何技術都不能操之過急,要把基礎打紮實了,這樣學什麼都會很快。

http://www.nowamagic.net/librarys/veda/detail/1579

昨天收到一封來自深圳的一位前端童鞋的郵件,郵件內容如下(很抱歉,未經過他的允許,公開郵件內容,不過我相信其他人肯定也有同樣的問題,所以,直接把問題原文丟擲來):

“讀了你的幾篇關於JS(變數物件、作用域、上下文、執行程式碼)的文章,我個人覺得有點抽象,難以深刻理解。我想請教下通過什麼途徑能夠深入點的瞭解javascript解析引擎在執行程式碼前後是怎麼工作的,ecma英文版實在看不下去呵呵。”

其實這個問題個人覺得太籠統了,直接回答很難回答,所以,我打算先把他的問題拆解成如下幾個子問題,並對其表達個人的觀點,希望對有同樣困惑的童鞋能夠有所幫助。

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的語法
  • 定義了對錶達式,語句等標準的處理演算法,比如遇到==該如何處理
  • ⋯⋯

注:js相容性問題的原因

標準的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的程序切換、函式相關的的區域性變數的棧儲存、函式退出的操作等等都是一致的。

以上就是個人對這個問題的看法,除此之外,我覺得,學習任何技術都不能操之過急,要把基礎打紮實了,這樣學什麼都會很快。