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

「Node.js系列」深入淺出講解V8引擎如何執(zhí)行JavaScript代碼

開發(fā) 后端
本文將為大家介紹,V8引擎如何執(zhí)行JavaScript代碼。

[[345748]]

 看完本文可以掌握,以下幾個方面:

  • JavaScript的執(zhí)行原理;
  • 瀏覽器內(nèi)核的真實結(jié)構(gòu);
  • 瀏覽器渲染引擎的工作過程;
  • V8引擎的工作原理;
  • 瀏覽器和Node.js架構(gòu)的區(qū)別和練習(xí);
  • Node.js架構(gòu)的應(yīng)用場景和REPL;
  • Node.js架構(gòu)的REPL使用;

PS:本篇文章為「Node.js系列」的第一篇,為邂逅Node.js。

之后會保持每周1~2篇的Node.js文章,歡迎大家和我一起學(xué)習(xí)大前端進階系列。

題目中說到的V8引擎,大家自然會聯(lián)想到Node.js。

我們先看一下官方對Node.js的定義:

Node.js是一個基于V8 JavaScript引擎的JavaScript運行時環(huán)境

但是這句話對于我們很多同學(xué)來說,非?;\統(tǒng),比如先拋出這樣幾個問題:

  • 什么是JavaScript運行環(huán)境?
  • 為什么JavaScript需要特別的運行環(huán)境呢?
  • JavaScript引擎又是什么呢?
  • V8是什么?

上面這些問題,同學(xué)們理解的籠統(tǒng)沒關(guān)系,這篇文章會依次揭曉答案~

我們先來吧這些概念搞清楚,再去看Node到底是什么?為什么大前端需要它。

JavaScript無處不在
Stack Overflow的創(chuàng)立者之一的 Jeff Atwood 在前些年提出了著名的Atwood定律:

  • 任何可以使用JavaScript來實現(xiàn)的應(yīng)用最終都會使用JavaScript實現(xiàn)。

在發(fā)明之處,JavaScript的目的是應(yīng)用于在瀏覽器執(zhí)行簡單的腳本任務(wù),對瀏覽器以及其中的DOM進行各種操作,所以JavaScript的應(yīng)用場景非常受限。

但是隨著Node的出現(xiàn),Atwood定律已經(jīng)越來越多的被證實是正確的。

但是為了可以理解Node.js是如何幫助我們做到這一點的,我們必須了解JavaScript是如何被運行的。

現(xiàn)在我們想一下,JavaScript代碼在瀏覽器中是如何被執(zhí)行的呢?

瀏覽器內(nèi)核
不同的瀏覽器有不同的內(nèi)核組成:

  • Gecko:早期被Netscape和Mozilla Firefox瀏覽器使用;
  • Trident:微軟開發(fā),被IE4~IE11瀏覽器使用,但是Edge瀏覽器已經(jīng)轉(zhuǎn)向Blink;
  • Webkit:蘋果基于KHTML開發(fā)、開源的,用于Safari,Google Chrome之前也在使用;
  • Blink:是Webkit的一個分支,Google開發(fā),目前應(yīng)用于Google Chrome、Edge、Opera等;
  • 等等...

事實上,我們經(jīng)常說的瀏覽器內(nèi)核指的是瀏覽器的排版引擎:

排版引擎(layout engine),也稱為瀏覽器引擎(browser engine)、頁面渲染引擎(rendering engine)或樣板引擎。

介紹完瀏覽器的排版引擎之后,來介紹下瀏覽器的渲染引擎的工作過程。

渲染引擎工作的過程

瀏覽器渲染引擎的工作過程

如上圖:

  • HTML和CSS經(jīng)過對應(yīng)的Parser解析之后,會形成對應(yīng)的DOM Tree和 CSS Tree;
  • 它們經(jīng)過附加合成之后,會形成一個Render Tree,同時生成一個Layout布局,最終通過瀏覽器的渲染引擎幫助我們完成繪制,展現(xiàn)出平時看到的Hmtl頁面;
  • 在HTML解析過程中,如果遇到了<script src='xxx'>,會停止解析HTML,而優(yōu)先去加載和執(zhí)行JavaScript代碼(此過程由JavaScript引擎完成)

因為JavaScript屬于高級語言(Python、C++、Java),所以JavaScript引擎會先把它轉(zhuǎn)換成匯編語言,再把匯編語言轉(zhuǎn)換成機器語言(二進制010101),最后被CPU所執(zhí)行。

JavaScript引擎
為什么需要JavaScript引擎呢?

  • 事實上我們編寫的JavaScript無論你交給瀏覽器或者Node執(zhí)行,最后都是需要被CPU執(zhí)行的;
  • 但是CPU只認識自己的指令集,實際上是機器語言,才能被CPU所執(zhí)行;
  • 所以我們需要JavaScript引擎幫助我們將JavaScript代碼翻譯成CPU指令來執(zhí)行;

比較常見的JavaScript引擎有哪些呢?

  • SpiderMonkey:第一款JavaScript引擎,由Brendan Eich開發(fā)(也就是JavaScript作者);
  • Chakra:微軟開發(fā),用于IT瀏覽器;
  • JavaScriptCore:WebKit中的JavaScript引擎,Apple公司開發(fā);
  • V8:Google開發(fā)的強大JavaScript引擎,也幫助Chrome從眾多瀏覽器中脫穎而出;

上面我們介紹了JavaScript引擎和瀏覽器內(nèi)核,但有的同學(xué)就該問了它們倆之間有什么聯(lián)系呢和不同呢?

下面,我以WebKit內(nèi)核為例。

WebKit內(nèi)核
事實上WebKit內(nèi)核由兩部分組成的:

WebCore:負責(zé)HTML解析、布局、渲染等等相關(guān)的工作;
JavaScriptCore:解析、執(zhí)行JavaScript代碼(JavaScript引擎的工作)。

另外一個強大的JavaScript引擎就是V8引擎。

V8引擎
我們來看一下官方對V8引擎的定義:

  • 支持語言:V8是用C ++編寫的Google開源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等;

         (譯:V8可以運行JavaScript和WebAssembly引擎編譯的匯編語言等)

  • 跨平臺:它實現(xiàn)ECMAScript和WebAssembly,并在Windows 7或更高版本,macOS 10.12+和使用x64,IA-32,

          ARM或MIPS處理器的Linux系統(tǒng)上運行;

  • 嵌入式:V8可以獨立運行,也可以嵌入到任何C ++應(yīng)用程序中;

V8引擎的工作原理
圖解V8引擎的工作原理

圖解V8引擎的工作原理

其中的**Parse(解析器)、lgnition(解釋器)、TurboFan(優(yōu)化編譯器)**都是V8引擎的內(nèi)置模塊

假如有這樣一段JavaScript源代碼:

  1. console.log("hello world"); 
  2.  
  3. function sum(num1, num2) { 
  4.  return num1 + num2; 
  • Parse模塊會將JavaScript代碼轉(zhuǎn)換成AST(抽象語法樹),這是因為解釋器并不直接認識JavaScript代碼;
  • 如果函數(shù)沒有被調(diào)用,那么是不會被轉(zhuǎn)換成AST的;
  • Parse的V8官方文檔:https://v8.dev/blog/scanner
  • Ignition是一個解釋器,會將AST轉(zhuǎn)換成ByteCode(字節(jié)碼);
  • 同時會收集TurboFan優(yōu)化所需要的信息(比如函數(shù)參數(shù)的類型信息,有了類型才能進行真實的運算);
  • 如果函數(shù)只調(diào)用一次,Ignition會執(zhí)行解釋執(zhí)行ByteCode;
  • Ignition的V8官方文檔:https://v8.dev/blog/ignition-interpreter
  • TurboFan是一個編譯器,可以將字節(jié)碼編譯為CPU可以直接執(zhí)行的機器碼;
  • 如果一個函數(shù)被多次調(diào)用,那么就會被標(biāo)記為熱點函數(shù),那么就會經(jīng)過TurboFan轉(zhuǎn)換成優(yōu)化的機器碼,提高代碼的執(zhí)行性能;
  • 但是,機器碼實際上也會被還原為ByteCode,這是因為如果后續(xù)執(zhí)行函數(shù)的過程中,類型發(fā)生了變化(比如sum函數(shù)原來執(zhí)行的是number類型,后來執(zhí)行變成了string類型),之前優(yōu)化的機器碼并不能正確的處理運算,就會逆向的轉(zhuǎn)換成字節(jié)碼;
  • TurboFan的V8官方文檔:https://v8.dev/blog/turbofan-jit
  • 上面是JavaScript代碼的執(zhí)行過程,事實上V8的內(nèi)存回收也是其強大的另外一個原因;
  • Orinoco模塊,負責(zé)垃圾回收,將程序中不需要的內(nèi)存回收;
  • Orinoco的V8官方文檔:https://v8.dev/blog/trash-talk
  • 關(guān)于V8引擎的垃圾內(nèi)存回收機制,可以看下我之前整理的這篇文章「經(jīng)典升華」V8引擎的垃圾內(nèi)存回收機制

編程語言會大體分為兩大類:

  • 解釋型語言:運行效率相對較低(比如JavaScript)
  • 編譯型語言:運行效率相對較高(比如C++)

上述情況對應(yīng)的是JavaScript解釋性語言的大體執(zhí)行流程,但編譯性語言往往不是,比如C++,例如系統(tǒng)內(nèi)的某些應(yīng)用程序用C++編寫的,它們在執(zhí)行的時候會直接轉(zhuǎn)化為機器語言(二進制格式010101),并交給CPU統(tǒng)一執(zhí)行,這樣的運行效率自然相對較高了些。

但V8也對解釋性的編程語言做了一個優(yōu)化,就是上文提到的TurboFan優(yōu)化編譯器,如果一個JavaScript函數(shù)被多次調(diào)用,那么它就會經(jīng)過TurboFan抓成優(yōu)化后的機器碼,交由CPU執(zhí)行,提高代碼的執(zhí)行性能。

回顧:Node.js是什么
回顧:官方對Node.js的定義:

Node.js是一個基于V8 JavaScript引擎的JavaScript運行時環(huán)境。

也就是說Node.js基于V8引擎來執(zhí)行JavaScript的代碼,但是不僅僅只有V8引擎:

  • 前面我們了解到V8可以嵌入到任何C ++應(yīng)用程序中,無論是Chrome還是Node.js,事實上都是嵌入了V8引擎

          來執(zhí)行JavaScript代碼;

  • 但是在Chrome瀏覽器中,還需要解析、渲染HTML、CSS等相關(guān)渲染引擎,另外還需要提供支持瀏覽器操作

           的API、瀏覽器自己的事件循環(huán)等,這些都是由瀏覽器內(nèi)核幫我們完成的;

  • 另外,在Node.js中我們也需要進行一些額外的操作,比如文件系統(tǒng)讀/寫、網(wǎng)絡(luò)IO、加密、壓縮解壓文件等

 

PS:在后面的文章我們,我會帶領(lǐng)大家逐步探索Node.js的世界...

瀏覽器和Node.js架構(gòu)區(qū)別
簡單對比一下Node.js和瀏覽器架構(gòu)的差異:

瀏覽器和Node.js架構(gòu)區(qū)別

  • 在Chrome瀏覽器中
  • 比如發(fā)送網(wǎng)絡(luò)請求,中間層會調(diào)用操作系統(tǒng)中的網(wǎng)卡;
  • 讀取一些本地文件,中間層會調(diào)用操作系統(tǒng)中的硬盤;
  • 瀏覽器頁面的渲染工作,中間層會調(diào)用操作系統(tǒng)中的顯卡;
  • 等等...
  • V8引擎只是其中的一小部分,用來輔助JavaScript代碼的運行;
  • 還有一些瀏覽器的內(nèi)核用來負責(zé)HTML解析、布局、渲染等等相關(guān)的工作;
  • 中間層和操作系統(tǒng)(網(wǎng)卡/硬盤/顯卡...);
  • 在Node中
  • V8引擎;
  • 中間層(libuv)包括EventLoop等;
  • 操作系統(tǒng)(網(wǎng)卡/硬盤/顯卡...);

Node.js架構(gòu)
我們來看一個單獨的Node.js的架構(gòu)圖:

  • 我們編寫的JavaScript代碼會經(jīng)過V8引擎,再通過Node.js的Bindings(Node.js API),將任務(wù)派發(fā)到Libuv的事件循環(huán)中;
  • Libuv提供了事件循環(huán)、文件系統(tǒng)讀寫、網(wǎng)絡(luò)IO、線程池等等內(nèi)容;Libuv是使用C語言編寫的庫;

具體的內(nèi)部代碼執(zhí)行流程,我會在后面的文章中專門講解Node.js中的事件隊列機制和異步IO的原理;

Node.js架構(gòu)圖

Node.js的應(yīng)用場景
Node.js的快速發(fā)展也讓企業(yè)對Node.js技術(shù)越來越重視。

那么它都有哪些實際的應(yīng)用場景呢?

  • 目前前端開發(fā)的庫都是以node包的形式進行管理;
  • npm、yarn工具成為前端開發(fā)使用最多的工具;
  • 越來越多的公司使用Node.js作為web服務(wù)器開發(fā);
  • 大量項目需要借助Node.js完成前后端渲染的同構(gòu)應(yīng)用;
  • 很多企業(yè)在使用Electron來開發(fā)桌面應(yīng)用程序;

Node.js的REPL
什么是REPL呢?感覺挺高大上

  • REPL是Read-Eval-Print Loop的簡稱,翻譯為 “讀取-求值-輸出”循環(huán);
  • REPL是一個簡單的、交互式的編程環(huán)境;

事實上,我們?yōu)g覽器的console就可以看成一個REPL。

Node也給我們提供了一個REPL環(huán)境,我們可以在其中演練簡單的代碼。

瀏覽器的REPL

Node的REPL

責(zé)任編輯:姜華 來源: 前端時光屋
相關(guān)推薦

2020-10-12 06:35:34

V8JavaScript

2022-06-21 08:52:47

Node.js服務(wù)端JavaScript

2022-02-25 08:32:07

nodemon搭Node.jsJavascript

2020-11-09 10:46:35

CommonJS

2022-06-02 12:02:12

V8C++JavaScript

2017-12-17 16:34:18

JavaScript代碼V8

2024-07-08 08:53:52

2020-09-27 07:32:18

V8

2022-09-26 09:01:15

語言數(shù)據(jù)JavaScript

2022-09-16 08:32:25

JavaC++語言

2022-10-31 09:00:24

Promise數(shù)組參數(shù)

2012-02-21 13:55:45

JavaScript

2009-08-21 10:09:02

Google ChroV8引擎linux系統(tǒng)

2023-06-05 16:38:51

JavaScript編程語言V8

2023-12-04 13:22:00

JavaScript異步編程

2010-07-16 09:11:40

JavaScript內(nèi)存泄漏

2018-12-25 08:00:00

2012-03-28 13:34:09

紅帽Node.js支持

2011-05-30 14:41:09

Javascript閉

2021-05-24 11:25:13

Node.js 16V8前端
點贊
收藏

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