1. 
          

          1. 新聞動(dòng)態(tài)

            JavaScript 運行原理

            常見(jiàn)問(wèn)題 發(fā)布者:cya 2019-12-12 08:35 訪(fǎng)問(wèn)量:201

            譯文:梁天培

            鏈接:https://juejin.im/post/5d84ae08e51d4561a705bbde

            原文鏈接:https://blog.bitsrc.io/javascript-under-the-hood-632ccae06b27

            最初,JavaScript 只能在 Web 瀏覽器中運行,但是隨著(zhù) Node 的出現,現在 JavaScript 也可以在服務(wù)端運行。雖然我們可能知道應該在何時(shí)何地去使用它, 但是我們真的了解這些腳本執行的背后發(fā)生了什么嗎?

            如果您覺(jué)得自己對 JavaScript 引擎有了一些了解的話(huà),可以先給自己鼓個(gè)掌,但不要急著(zhù)關(guān)掉本文,我相信閱讀完成后您仍然可以從中學(xué)到一些東西。

            JavaScript 是一門(mén)高級語(yǔ)言,但是最終計算機能理解只有1和0。那么我們編寫(xiě)的代碼是如何被計算機理解的呢?掌握所學(xué)編程語(yǔ)言的基礎知識將讓您能編寫(xiě)出更好的代碼。在本文中,我們僅探討一個(gè)問(wèn)題:JavaScript 是如何工作的?

            JavaScript 引擎

            這是本文將要探索的主要內容,它負責使計算機理解我們編寫(xiě)的 JS 代碼。JavaScript 引擎是一種用于將我們的代碼轉換為機器可讀語(yǔ)言的引擎。如果沒(méi)有 JavaScript 引擎,您編寫(xiě)的代碼對計算機來(lái)說(shuō)簡(jiǎn)直是一堆“胡言亂語(yǔ)”。不僅僅是 JavaScript ,其他所有編程語(yǔ)言都需要一個(gè)類(lèi)似的引擎,來(lái)將這些“胡言亂語(yǔ)”轉換成對計算機有意義的語(yǔ)言。

            目前有多種 JavaScript 引擎在可供使用。您可以在 Wikipedia 上查閱所有可用的 JavaScript 引擎。它們也被稱(chēng)為 ECMAScript 引擎,這樣叫的具體原因會(huì )在下文中提及。下面是一些我們日??赡軙?huì )用到的 JavaScript 引擎:

            • Chakra, Microsoft IE/Edge

            • SpiderMonkey, FireFox

            • V8, Chrome

            除此之外的其它引擎,可以自行搜索了解。接下來(lái),我們將深入研究這些引擎,以了解它們是如何翻譯 JavaScript 文件的。

            JavaScript 引擎的內里

            我們已經(jīng)知道了引擎是必須的,由此可能不禁會(huì )想:

            是誰(shuí)發(fā)明了 JavaScript 引擎?

            答案是,任何人都可以。它只是分析我們的代碼并將其翻譯的另一種語(yǔ)言的工具。V8 是最受歡迎的 JavaScript 引擎之一,也是 Chrome 和 NodeJS 使用的引擎。它是用 C++(一種底層語(yǔ)言)編寫(xiě)的。但是如果每個(gè)人都創(chuàng )造一個(gè)引擎,那場(chǎng)面就不是可控范圍內的了。

            因此,為了給這些引擎確立一個(gè)規范,ECMA 的標準誕生了,該標準主要提供如何編寫(xiě)引擎和 JavaScript 所有功能的規范。這就是新功能能在 ECMAScript 6、7、8 上實(shí)現的原因。同時(shí),引擎也進(jìn)行了更新以支持這些新功能。于是,我們便可以在開(kāi)發(fā)過(guò)程中檢查了瀏覽器中 JS 高級功能的可用性。

            下面我們對 V8 引擎進(jìn)行進(jìn)一步的探索,因為基本概念在所有引擎中是一致的。

            JavaScript V8 Engine

            上圖就是 JS Engine 內部的工作流程。我們輸入的代碼將通過(guò)以下階段,

            • Parser

            • AST

            • Interpreter 生成 ByteCode

            • Profiler

            • Compiler 生成優(yōu)化后的代碼

            別被上面的流程給唬住了,在幾分鐘后您將了解它們是協(xié)同運作的。

            在進(jìn)一步深入這些階段之前,您需要先了解 Interpreter 和 Compiler 的區別。

            Interpreter VS Compiler

            通常,將代碼轉換成機器可讀語(yǔ)言的方法有兩種。我們將要討論的概念不僅適用于 JavaScript ,而且適用于大多數編程語(yǔ)言,例如 Python,Java 等。

            • Interpreter 逐行讀取代碼并立即執行。

            • Compiler 讀取您的整個(gè)代碼,進(jìn)行一些優(yōu)化,然后生成優(yōu)化后的代碼。

            讓我們來(lái)看下面這個(gè)例子。

            function add(a, b{
                return a+b
            }
            for(let i = 0; i < 1000; i++) {
                add(1 + 1)
            }

            上面的示例循環(huán)調用了 add 函數1000次,該函數將兩個(gè)數字相加并返回總和。

            Interpreter 接收上面的代碼后,它將逐行讀取并立即執行代碼,直到循環(huán)結束。它的工作僅僅是實(shí)時(shí)地將代碼轉換為我們的計算機可以理解的內容。

            如果這段代碼接受者是 Compiler,它會(huì )先完整地讀取整個(gè)程序,對我們要執行的代碼進(jìn)行分析,并生成電腦可以讀懂的機器語(yǔ)言。過(guò)程如同獲取 X(我們的JS文件)并生成 Y(機器語(yǔ)言)一樣。如果我們使用 Interpreter 執行 Y,則會(huì )獲得與執行 X 相同的結果。

            從上圖中可以看出,ByteCode 只是中間碼,計算機仍需要對其進(jìn)行翻譯才能執行。但是 Interpreter 和 Compiler 都將源代碼轉換為機器語(yǔ)言,它們唯一的區別在于轉換的過(guò)程不盡相同。

            • Interpreter 逐行將源代碼轉換為等效的機器代碼。

            • Compiler 在一開(kāi)始就將所有源代碼轉換為機器代碼。

            如果你想了解更多它們之前的區別,推薦閱讀這篇文章。

            當您閱讀完上面的推薦文章后,您可能已經(jīng)了解到 Babel 實(shí)際上是一個(gè) JS Compiler ,它可以接收您編寫(xiě)的新版本 JS 代碼并向下編譯為與瀏覽器兼容的 JS 代碼(舊版本的 JS 代碼)。

            Interpreter 和 Compiler 的優(yōu)缺點(diǎn)

            Interpreter 的優(yōu)點(diǎn)是無(wú)需等待編譯即可立即執行代碼。這對在瀏覽器中運行 JS 提供了極大的便利,因為所有用戶(hù)都不想浪費時(shí)間在等待代碼編譯這件事上。但是,當有大量的 JS 代碼需要執行時(shí)會(huì )運行地比較慢。還記得上面例子中的那一小段代碼嗎?代碼中執行了1000次函數調用。函數 add 被調用了1000次,但他的輸出保持不變。但是 Interpreter 還是逐行執行,會(huì )顯得比較慢。

            在同樣的情況下,Compiler 可以通過(guò)用2代替循環(huán)(因為 add 函數每次都是執行1 + 1)來(lái)進(jìn)行一些優(yōu)化。Compiler 最終給出的優(yōu)化代碼可以在更短的時(shí)間內執行完成。

            綜上所述,Interpreter 可以立即開(kāi)始執行代碼,但不會(huì )進(jìn)行優(yōu)化。Compiler 雖然需要花費一些時(shí)間來(lái)編譯代碼,但是會(huì )生成對執行時(shí)更優(yōu)的代碼。

            好的,Interpreter 和 Compiler 必要知識我們已經(jīng)了解了。現在讓我們回到主題——JS 引擎。

            因此,考慮到編譯器和解釋器的優(yōu)缺點(diǎn),如果我們同時(shí)利用兩者的優(yōu)點(diǎn),該怎么辦?這就是 JIT(Just In Time) Compiler 的用武之地。它是 Interpreter 和 Compiler 的結合,現在大多數瀏覽器都在更快,更高效地實(shí)現此功能。同時(shí) V8 引擎也使用此功能。

            JavaScript V8 Engine

            在這個(gè)過(guò)程中,

            Parser 是一種通過(guò)各種 JavaScript 關(guān)鍵字來(lái)識別,分析和分類(lèi)程序各個(gè)部分的解析器。它可以區分代碼是一個(gè)方法還是一個(gè)變量。

            然后,AST(抽象語(yǔ)法樹(shù)) 基于 Parser 的分類(lèi)構造樹(shù)狀結構。您可以使用 AST Explorer 查看該樹(shù)的結構。

            隨后將 AST 提供給 Interpreter 生成 ByteCode。如上文所述,ByteCode 不是最底層的代碼,但可以被執行。在此階段,瀏覽器借助 V8 引擎執行 ByteCode 進(jìn)行工作,因此用戶(hù)無(wú)需等待。

            同時(shí),Profiler 將查找可以被優(yōu)化的代碼,然后將它們傳遞給 Compiler。Compiler 生成優(yōu)化代碼的同時(shí),瀏覽器暫時(shí)用 ByteCode 執行操作。并且,一旦 Compiler 生成了優(yōu)化代碼,優(yōu)化代碼則將完全替換掉臨時(shí)的 ByteCode。

            通過(guò)這種方式,我們可以充分利用 Interpreter 和 Compiler 的優(yōu)點(diǎn)。Interpreter 執行代碼的同時(shí),Profiler 尋找可以被優(yōu)化的代碼,Compiler 則創(chuàng )建優(yōu)化的代碼。然后,將 ByteCode 碼替換為優(yōu)化后的較為底層的代碼,例如機器代碼。

            這僅意味著(zhù)性能將在逐漸提高,同時(shí)不會(huì )有阻塞執行的時(shí)間。

            關(guān)于 ByteCode

            作為機器代碼,ByteCode 不能被所有計算機理解及執行。它仍然需要像虛擬機或像 Javascript V8 引擎這樣的中間件才能將其轉換為機器可讀的語(yǔ)言。這就是為什么我們的瀏覽器可以在上述5個(gè)階段中借助 JavaScript 引擎在 Interpreter 中執行 ByteCode 的原因。

            所以您可以會(huì )有另一個(gè)問(wèn)題,

            JavaScript 是一門(mén)解釋型語(yǔ)言嗎?

            JavaScript 是但不完全是一門(mén)解釋型語(yǔ)言。Brendan Eich 最初是在 JavaScript 的早期階段創(chuàng )建 JavaScript 引擎 “ SpiderMonkey” 的。該引擎有一個(gè) Interpreter 來(lái)告訴瀏覽器該怎么執行代碼。但是現在我們的引擎不僅包括了 Interpreter,還有 Compiler。我們的代碼不僅可以被轉換成 ByteCode,還可以被編譯輸出優(yōu)化后的代碼。因此,從技術(shù)上講,這完全取決于引擎是如何實(shí)現的。

            JavaScript 引擎的整體工作原理就是這樣。相信您無(wú)需學(xué)習 JavaScript 也可以理解。當然,您甚至可以在不知道 JavaScript 如何工作的情況下編寫(xiě)代碼。但是,如果我們了解一些幕后的知識,或許能讓我們編寫(xiě)出更好的代碼。



            關(guān)鍵字: JavaScript 運行原理 開(kāi)封網(wǎng)站建設

            文章連接: http://www.gostscript.com/cjwt/643.html

            版權聲明:文章由 晨展科技 整理收集,來(lái)源于互聯(lián)網(wǎng)或者用戶(hù)投稿,如有侵權,請聯(lián)系我們,我們會(huì )立即刪除。如轉載請保留

            双腿国产亚洲精品无码不卡|国产91精品无码麻豆|97久久久久久久极品|无码人妻少妇久久中文字幕
                1.