自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

揭開JavaScript引擎的面紗

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

 [[278966]]

前言

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

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

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

下面讓我們進(jìn)入正題~

JavaScript 引擎

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

目前有多種 JavaScript 引擎在可供使用。您可以在 Wikipedia 上查閱所有可用的 JavaScript 引擎。它們也被稱為 ECMAScript 引擎,這樣叫的具體原因會在下文中提及。 下面是一些我們?nèi)粘?赡軙玫降?JavaScript 引擎:

  •  Chakra, Microsoft IE/Edge
  •  SpiderMonkey, FireFox
  •  V8, Chrome

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

JavaScript 引擎的內(nèi)里

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

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

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

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

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

JavaScript V8 Engine

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

  1.  Parser
  2.  AST
  3.  Interpreter 生成 ByteCode
  4.  Profiler
  5.  Compiler 生成優(yōu)化后的代碼

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

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

Interpreter VS Compiler

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

  •  Interpreter 逐行讀取代碼并立即執(zhí)行。
  •  Compiler 讀取您的整個代碼,進(jìn)行一些優(yōu)化,然后生成優(yōu)化后的代碼。

讓我們來看下面這個例子。 

  1. function add(a, b) {  
  2.  return a+b  
  3.  
  4. for(let i = 0; i < 1000; i++) {  
  5.  add(1 + 1)  

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

  1.  Interpreter 接收上面的代碼后,它將逐行讀取并立即執(zhí)行代碼,直到循環(huán)結(jié)束。 它的工作僅僅是實時地將代碼轉(zhuǎn)換為我們的計算機可以理解的內(nèi)容。
  2.  如果這段代碼接受者是 Compiler,它會先完整地讀取整個程序,對我們要執(zhí)行的代碼進(jìn)行分析,并生成電腦可以讀懂的機器語言。過程如同獲取 X(我們的JS文件)并生成 Y(機器語言)一樣。如果我們使用 Interpreter 執(zhí)行 Y,則會獲得與執(zhí)行 X 相同的結(jié)果。

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

  •  Interpreter 逐行將源代碼轉(zhuǎn)換為等效的機器代碼。
  •  Compiler 在一開始就將所有源代碼轉(zhuǎn)換為機器代碼。

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

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

  •  Interpreter 的優(yōu)點是無需等待編譯即可立即執(zhí)行代碼。這對在瀏覽器中運行 JS 提供了極大的便利,因為所有用戶都不想浪費時間在等待代碼編譯這件事上。但是,當(dāng)有大量的 JS 代碼需要執(zhí)行時會運行地比較慢。還記得上面例子中的那一小段代碼嗎?代碼中執(zhí)行了1000次函數(shù)調(diào)用。函數(shù) add 被調(diào)用了1000次,但他的輸出保持不變。但是 Interpreter 還是逐行執(zhí)行,會顯得比較慢。
  •  在同樣的情況下,Compiler 可以通過用2代替循環(huán)(因為 add 函數(shù)每次都是執(zhí)行1 + 1)來進(jìn)行一些優(yōu)化。Compiler 最終給出的優(yōu)化代碼可以在更短的時間內(nèi)執(zhí)行完成。

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

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

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

 

在這個過程中,

  1.  Parser 是一種通過各種 JavaScript 關(guān)鍵字來識別,分析和分類程序各個部分的解析器。它可以區(qū)分代碼是一個方法還是一個變量。
  2.  然后,AST(抽象語法樹) 基于 Parser 的分類構(gòu)造樹狀結(jié)構(gòu)。您可以使用 AST Explorer 查看該樹的結(jié)構(gòu)。
  3.     隨后將 AST 提供給 Interpreter 生成 ByteCode。如上文所述,ByteCode 不是最底層的代碼,但可以被執(zhí)行。在此階段,瀏覽器借助 V8 引擎執(zhí)行 ByteCode 進(jìn)行工作,因此用戶無需等待。
  4.  同時,Profiler 將查找可以被優(yōu)化的代碼,然后將它們傳遞給 Compiler。Compiler 生成優(yōu)化代碼的同時,瀏覽器暫時用 ByteCode 執(zhí)行操作。并且,一旦 Compiler 生成了優(yōu)化代碼,優(yōu)化代碼則將完全替換掉臨時的 ByteCode。

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

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

關(guān)于 ByteCode

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

所以您可以會有另一個問題,

JavaScript 是一門解釋型語言嗎?

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

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

 

責(zé)任編輯:龐桂玉 來源: 今日頭條
相關(guān)推薦

2022-01-16 18:51:57

.NET 6Configurati配置

2013-09-22 11:03:20

SocketSocket編程

2015-08-20 13:43:17

NFV網(wǎng)絡(luò)功能虛擬化

2009-09-08 16:30:18

網(wǎng)銀木馬

2010-05-17 09:13:35

2014-03-12 11:11:39

Storage vMo虛擬機

2021-06-07 08:18:12

云計算云端阿里云

2023-06-07 13:43:49

云計算

2010-05-26 19:12:41

SVN沖突

2009-12-03 09:19:41

Linux系統(tǒng)奧秘

2009-06-01 09:04:44

Google WaveWeb

2018-03-01 09:33:05

軟件定義存儲

2016-04-06 09:27:10

runtime解密學(xué)習(xí)

2009-09-15 15:34:33

Google Fast

2023-11-02 09:55:40

2025-01-08 15:44:04

2016-11-10 12:49:00

2016-11-16 09:06:59

2024-02-14 09:00:00

機器學(xué)習(xí)索引ChatGPT

2025-01-07 15:07:13

點贊
收藏

51CTO技術(shù)棧公眾號