javascript依賴於什麼支援

2022-09-30 18:01:43

javascript依賴於底層javascript引擎的支援。javascript執行在瀏覽器,主要依靠瀏覽器的js引擎解釋執行js程式碼;JavaScript引擎是一個專門處理JavaScript指令碼的虛擬機器器,一般會附帶在網頁瀏覽器之中,用於解釋和執行js指令碼。

前端(vue)入門到精通課程:進入學習
API 檔案、設計、偵錯、自動化測試一體化共同作業工具:

本教學操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。

javascript依賴於底層js引擎的支援。

javascript執行在瀏覽器,主要依靠瀏覽器的js引擎解釋執行js程式碼。其他帶有js引擎的軟體也可以執行js,但是一般js和網頁關係較大,所以一般在瀏覽器當中執行。

javascript引擎

JavaScript引擎是一個專門處理JavaScript指令碼的虛擬機器器,一般會附帶在網頁瀏覽器之中,用於解釋和執行js指令碼。

著名的js引擎:

    Mozilla:SpiderMonkey引擎,世界第一款JavaScript引擎,有C/C++編寫,用於Mozilla Firefox 1.0~3.0版本

    Google:V8引擎,由C++/組合語言編寫,用於chrome瀏覽器

    微軟:Chakra(查克拉,笑)引擎,用於Internet Explorer 9的32位元版本

瀏覽器核心和JS引擎的關係

以webkit為例:

1.png

V8引擎

1、V8引擎的原理

V8引擎是用C++編寫的Google開源高效能的JavaScript和WebAssembly引擎,用於Chrome和Node.js等。

它能夠實現ECMAScript和WebAssembly,並在Windows7或者更高版本,macOS 10.12+和使用x64,IA-32,ARM或MIPS處理器的Linux系統上執行。

V8引擎可以獨立執行,也可以嵌入到任何C++應用程式中執行。例如,可以將V8引擎中使用Node.js看做是將將V8引擎嵌入到了應用程式中,那麼Node.js就具備了執行JavaScript程式碼的能力。

原理圖:

2.png

①、Parse模組會將JavaScript程式碼轉換成AST,這是因為直譯器並不直接認識JavaScript程式碼。如果函數沒有被呼叫,是不會被轉換為AST的

②、Ignition是一個直譯器,會將AST轉換為ByteCode。同時會收集TurboFan優化所需的資訊(比如函數引數的型別資訊,有了型別才能真實的運算)。如果函數只呼叫一次,Ignition將AST轉換為ByteCode

③、為什麼最後轉化為位元組碼,而不是直接轉化為機器碼?

因為JS程式碼在什麼樣的環境下執行並不固定,有可能是使用Windows環境、或者是mac環境、或者是Linux環境的瀏覽器上,也可能是在Node.js中,環境不固定,不同環境中就會有不同的CPU,不同的CPU擁有不同的CPU架構,不同的架構能夠執行的機器指令是不一樣的。

3.png

轉化為V8引擎規定好的位元組碼,不管在什麼環境下都可以執行,是跨平臺的,最後V8引擎會把位元組碼轉化組合指令,再轉化為不同環境對應的CPU指令。

但是每次都走這套流程,還是不夠方便。比如有一個函數是重複使用的,但是使用前面一套流程,每次使用這個函數的時候,都需要被轉化為位元組碼,然後再變為CPU指令,效能比較低,如果可以直接將這個函數變為機器指令儲存下來,使用這個函數的時候,直接執行機器指令,效能比較高,但是如果這個函數只執行一次,就沒有必要轉化變為機器程式碼儲存下來,會浪費空間。

④、使用TurboFan庫,是一個編譯器,會將位元組碼編譯為CPU可以直接執行的機器碼,他可以利用ignition來收集函數的執行資訊,瞭解到哪些函數執行次數比較多,會將這類函數標記為hot ,熱函數,然後就會將這個函數轉換為優化之後的機器指令,以後再使用這個熱函數的時候,不需要上面繁瑣的過程,直接執行機器指令就行。

但是實際上機器碼也會被還原為ByteCode,這是因為如果後續執行函數的過程中,型別發生改變,之前優化的機器碼並不能正確地處理運算,就會逆向的轉換為位元組碼。

⑤、Deoptimization: 比如有一個函數

function  sum(num1,num2){
   num1+num2
}
登入後複製

呼叫sum函數

sum(20,30)
sum(28,30)
登入後複製

如果傳入數位,呼叫sum函數,需要做的工作就是對兩個數位進行相加,執行的機器指令永遠是對這兩個數位進行相加.
一旦改變傳入值的型別,如果變成字串,那麼這個函數的意思就是兩個字串拼接。

sum("aaa","bbb")
登入後複製

這兩種型別的傳入值執行「+」操作對應的機器指令是不同的,JavaScript是不會對傳入值的型別做檢測的,那麼還是使用數位相加的機器指令,這次函數呼叫的結果是不能夠使用的。

但是V8引擎中提供了一種解決辦法Deoptimization過程,這個過程是,一旦發現在執行機器指令時候,執行的操作不一樣的時候,Deoptimization會反向優化,又轉化為位元組碼,執行後續操作。

2、V8引擎的解析圖

4.png

V8執行的細節:

①、Blink將原始碼交給V8引擎,Stream獲取到原始碼並且進行編碼轉換

②、scanner會進行詞法分析,詞法分析之後會將程式碼轉換為成tokens

③、tokens會被轉換為AST樹,經過Parser和PreParser:

Parser就是直接將tokens轉換為AST樹架構;

PreParser預解析,為什麼會需要預解析?

1)如上圖中的函數outer(),內部有一個函數inner(),但是並沒有任何呼叫inner()的程式碼,那麼就意味著並不是所有的JavaScript程式碼,都是一開始就被執行。對所有的JavaScript程式碼進行解析,必定會影響網頁的執行效率。

2)V8引擎實現了Lazy Parsing(延遲解析)的方案,作用是將不必要的函數進行預解析,我只需要知道有這麼個函數就行,也就是隻解析暫時需要的內容,對函數的全量解析在函數被呼叫的時候才會執行。

3)例如上圖中函數outer中的inner函數,它就是會執行預解析。

④、生成AST樹之後,會被Ignition轉成位元組碼,之後的過程就是程式碼的執行過程。

【相關推薦:、】

以上就是javascript依賴於什麼支援的詳細內容,更多請關注TW511.COM其它相關文章!