最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JS引擎中怎么在幕后工作

小編給大家分享一下JS引擎中怎么在幕后工作,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

我們提供的服務(wù)有:成都網(wǎng)站制作、做網(wǎng)站、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、奎屯ssl等。為超過千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的奎屯網(wǎng)站制作公司

介紹

您是否曾經(jīng)問過自己“這在幕后如何運(yùn)作?”。我知道我有

在接下來的系列文章中,我們將深入探討JS的世界,從引擎到幕后工作原理,從引擎到提升,執(zhí)行上下文,詞法環(huán)境等概念。

對(duì)某些概念有深刻的了解可以更好地理解代碼,在我們的工作中表現(xiàn)更好,此外,它在面試中非常有用。

而且這可能是一個(gè)非常有趣的學(xué)科……

在開始之前,還有一件重要的事情要提到-每個(gè)JS引擎的構(gòu)建方式都是不同的,因此無法涵蓋它們的全部工作原理。因此,我們將探索V8的工作原理,但是其他引擎中的概念仍然非常相似,只是其中一些引擎可能會(huì)實(shí)現(xiàn)不同的功能。

以下是V8工作原理的概述:

JS引擎中怎么在幕后工作

如果您還不了解這些內(nèi)容,請(qǐng)不要擔(dān)心,在本文結(jié)尾處,您將了解該圖的每個(gè)步驟。

因此,順便去吧!

環(huán)境

計(jì)算機(jī),編譯器甚至瀏覽器實(shí)際上無法“理解”用JS編寫的代碼。如果是這樣,代碼如何運(yùn)行?

在后臺(tái),JS始終在特定環(huán)境中運(yùn)行,最常見的是:

  • 瀏覽器(迄今為止最常見)

  • Node.js(這是一個(gè)運(yùn)行時(shí)環(huán)境,允許您在瀏覽器外部(通常在服務(wù)器中)運(yùn)行JS)

引擎

JS引擎中怎么在幕后工作

因此,JS需要在特定環(huán)境中運(yùn)行,但是該環(huán)境到底是什么?

當(dāng)您使用JS編寫代碼時(shí),會(huì)以人類可讀的語法(包括字母和數(shù)字)來編寫代碼。如前所述,機(jī)器無法理解此類代碼。

這就是每個(gè)環(huán)境都有引擎的原因。

通常,引擎的工作是獲取該代碼并將其轉(zhuǎn)換為用機(jī)器代碼編寫的代碼,該代碼最終可以由計(jì)算機(jī)處理器運(yùn)行。

每個(gè)環(huán)境都有自己的引擎,最常見的引擎是Chrome V8(Node也使用該引擎),F(xiàn)irefox SpiderMonkey,Safari的JavaScriptCore和IE的Chakra。

所有引擎的工作方式都相似,但是每個(gè)引擎之間存在差異。

同樣重要的是要記住,在后臺(tái)引擎只是一個(gè)軟件,例如Chrome V8是用C ++編寫的軟件。

解析器

JS引擎中怎么在幕后工作

因此,我們有一個(gè)環(huán)境,并且在該環(huán)境中有一個(gè)引擎。引擎在執(zhí)行代碼時(shí)要做的第一件事是使用解析器檢查代碼。

解析器了解JS語法和規(guī)則,它的工作是逐行檢查代碼,并檢查代碼的語法是否正確。

如果解析器遇到錯(cuò)誤,它將停止運(yùn)行并發(fā)出錯(cuò)誤。如果代碼有效,則解析器會(huì)生成稱為“抽象語法樹”(簡稱AST)的內(nèi)容

抽象語法樹(AST)

JS引擎中怎么在幕后工作

因此,我們的環(huán)境中有一個(gè)引擎,其中包含一個(gè)解析器,該解析器生成AST。但是什么是AST,為什么我們需要它?

AST是一種數(shù)據(jù)結(jié)構(gòu),它不是JS所獨(dú)有的,而是由許多其他語言的編譯器實(shí)際使用的(其中一些語言是Java,C#,Ruby,Python)。

AST只是代碼的樹形表示,引擎創(chuàng)建AST而不是直接編譯為機(jī)器代碼的主要原因是,當(dāng)您將代碼包含在樹數(shù)據(jù)結(jié)構(gòu)中時(shí),轉(zhuǎn)換為機(jī)器代碼更容易。

實(shí)際上,您可以查看AST的外觀,只需將任何代碼放入ASTExplorer網(wǎng)站中,并查看創(chuàng)建的數(shù)據(jù)結(jié)構(gòu):

JS引擎中怎么在幕后工作

解釋器

JS引擎中怎么在幕后工作

解釋器的工作是獲取已創(chuàng)建的AST,并將其轉(zhuǎn)換為代碼的中間表示(IR)。

我們將在需要進(jìn)一步上下文以充分了解其含義的基礎(chǔ)上,盡快了解有關(guān)解釋器的更多信息。

中級(jí)代表制(IR)

那么,解釋器從AST生成的IR是什么?

IR是代表源代碼的數(shù)據(jù)結(jié)構(gòu)或代碼。它的作用是介于以JS之類的抽象語言編寫的代碼與機(jī)器代碼之間的中間步驟。

本質(zhì)上,您可以將IR視為機(jī)器代碼的抽象。

IR的類型很多,在JS引擎中非常流行的是字節(jié)碼。這是一張圖片,展示了IR在V8引擎中的作用:

JS引擎中怎么在幕后工作

但是您可能會(huì)問……為什么我們需要IR?為什么不直接編譯為機(jī)器代碼呢?引擎將IR用作高級(jí)代碼和機(jī)器代碼之間的中間步驟的主要原因有兩個(gè):

  • 為Intel處理器編寫的機(jī)器代碼和為ARM處理器編寫的機(jī)器代碼將有所不同。另一方面,IR可以像通用的那樣匹配兩者,并且可以匹配任何平臺(tái)。這使得下面的轉(zhuǎn)換過程更加容易和移動(dòng)。

  • 優(yōu)化-與IR相比,使用IR進(jìn)行優(yōu)化更容易,從代碼優(yōu)化和硬件優(yōu)化的角度來看都是如此。

有趣的事實(shí):JS引擎并不是唯一使用字節(jié)碼作為IR的引擎,在也使用字節(jié)碼的語言中,您會(huì)發(fā)現(xiàn)C#,Ruby,Java等。

編譯器

JS引擎中怎么在幕后工作

編譯器的工作是獲取解釋器創(chuàng)建的IR(在我們的示例中為Bytecode),然后通過某些優(yōu)化將其轉(zhuǎn)換為機(jī)器代碼。

讓我們談?wù)劥a編譯和一些基本概念。請(qǐng)記住,這是一個(gè)巨大的主題,需要花費(fèi)大量時(shí)間來掌握,因此在我們的使用案例中,我將只對(duì)它進(jìn)行一般性的介紹。

解釋器vs編譯器

有兩種方法可以使用編譯器和解釋器將代碼轉(zhuǎn)換為機(jī)器可以運(yùn)行的機(jī)器語言。

解釋器和編譯器之間的區(qū)別在于,解釋器翻譯您的代碼并逐行執(zhí)行,而編譯器在執(zhí)行之前將所有代碼立即翻譯成機(jī)器代碼。

每種方法各有利弊,編譯器啟動(dòng)很快,但是復(fù)雜且啟動(dòng)緩慢,解釋器雖然簡單但速度較慢。

話雖如此,有3種方法可以將高級(jí)代碼轉(zhuǎn)換為機(jī)器代碼并運(yùn)行它:

  • 解釋-使用這種策略,您會(huì)有一個(gè)解釋器,它逐行執(zhí)行代碼并執(zhí)行(效率不高)。

  • 提前進(jìn)行時(shí)間編譯(AOT)-在這里,您需要一個(gè)編譯器來首先編譯整個(gè)代碼,然后才執(zhí)行它。

  • 即時(shí)編譯— JOT編譯策略結(jié)合了AOT策略和解釋策略,試圖從兩個(gè)方面吸取最大的優(yōu)勢,執(zhí)行動(dòng)態(tài)編譯,還允許進(jìn)行某些優(yōu)化,這實(shí)際上加快了編譯過程。我們將解釋有關(guān)JIT編譯的更多信息。

大多數(shù)JS引擎使用JIT編譯器,但不是全部。例如,React Native使用的引擎Hermes,沒有使用JIT編譯器。

綜上所述,編譯器采用由解釋器創(chuàng)建的IR并從中生成優(yōu)化的機(jī)器代碼。

JIT編譯器

就像我們說的那樣,大多數(shù)JS引擎都使用JIT編譯方法。JIT結(jié)合了AOT策略和解釋,允許進(jìn)行某些優(yōu)化。讓我們更深入地研究這些優(yōu)化以及編譯器的功能。

JIT編譯優(yōu)化是通過重復(fù)執(zhí)行代碼并對(duì)其進(jìn)行優(yōu)化來完成的。優(yōu)化過程如下:

本質(zhì)上,JIT編譯器通過收集執(zhí)行代碼的概要分析數(shù)據(jù)來獲得反饋,如果它遇到任何熱代碼段(重復(fù)自身的代碼),則該熱段將通過編譯器,然后編譯器將使用此信息重新更優(yōu)化地編譯。

假設(shè)您有一個(gè)函數(shù),該函數(shù)返回對(duì)象的屬性:

function load(obj) {    return obj.x; }

看起來簡單嗎?也許對(duì)我們來說,但是對(duì)于編譯器而言,這并不是一件容易的事。如果編譯器看到一個(gè)對(duì)象,它不知道任何東西,則它必須檢查屬性x的位置,如果該對(duì)象確實(shí)具有這樣的屬性,它在內(nèi)存中的位置,在原型鏈中的位置等等。

那么如何優(yōu)化它呢?

為了理解這一點(diǎn),我們必須知道在機(jī)器代碼中,對(duì)象及其類型已保存。

假設(shè)我們有一個(gè)具有x和y屬性的對(duì)象,x是數(shù)字類型,而y是字符串類型。從理論上講,該對(duì)象將用如下的機(jī)器代碼表示:

如果我們調(diào)用具有相同對(duì)象結(jié)構(gòu)的函數(shù),則可以完成優(yōu)化。這意味著屬性將相同且順序相同,但值可以不同,如下所示:

load({x: 1, y: 'hello'}); load({x: 5, y: 'world'}); load({x: 3, y: 'foo'}); load({x: 9, y: 'bar'});

運(yùn)作方式如下。調(diào)用該函數(shù)后,優(yōu)化的編譯器將識(shí)別出我們正在嘗試調(diào)用已被再次調(diào)用的函數(shù)。

然后,它將繼續(xù)檢查作為參數(shù)傳遞的對(duì)象是否具有相同的屬性。

如果是這樣,它將已經(jīng)能夠訪問其在內(nèi)存中的位置,而不用瀏覽原型鏈并完成對(duì)未知對(duì)象所做的許多其他事情。

本質(zhì)上,編譯器通過優(yōu)化和反優(yōu)化過程運(yùn)行。

當(dāng)我們運(yùn)行代碼時(shí),編譯器假定函數(shù)將使用與以前使用的類型相同的類型,因此它將代碼與類型預(yù)先保存在一起。這種類型的代碼稱為優(yōu)化機(jī)器代碼。

每次代碼再次調(diào)用相同的函數(shù)時(shí),優(yōu)化的編譯器將嘗試訪問內(nèi)存中的相同位置。

但是由于JS是一種動(dòng)態(tài)類型的語言,因此在某些時(shí)候,我們可能希望將相同的函數(shù)用于不同的類型。在這種情況下,編譯器將執(zhí)行去優(yōu)化過程,并正常地編譯代碼。

總結(jié)一下有關(guān)JIT編譯器的部分,JIT編譯器的工作是通過使用熱代碼段來提高性能,當(dāng)編譯器執(zhí)行之前執(zhí)行的代碼時(shí),它假定類型相同并且使用已生成的優(yōu)化代碼,但是如果類型不同,則JIT會(huì)執(zhí)行去優(yōu)化并正常地編譯代碼。

關(guān)于性能的說明

改善應(yīng)用程序性能的一種方法是對(duì)不同的對(duì)象使用相同的類型。如果您具有相同類型的兩個(gè)不同對(duì)象,即使值不同,只要屬性具有相同的順序并具有相同的類型,則編譯器會(huì)將這兩個(gè)對(duì)象視為具有相同結(jié)構(gòu)和類型的對(duì)象,并且可以更快地訪問它。

例如:

const obj = { x: 1, a: true, b: 'hey' }  const obj2 = { x: 7, a: false, b: 'hello' }

從示例中可以看到,我們有兩個(gè)具有不同值的不同對(duì)象,但是由于屬性的順序和類型相同,因此編譯器將能夠更快地編譯這些對(duì)象。

但是,即使有可能以這種方式優(yōu)化代碼,但我認(rèn)為對(duì)于性能而言,還有許多重要的事情要做,而這無關(guān)緊要的事情。

在團(tuán)隊(duì)中執(zhí)行這樣的事情也很困難,并且由于引擎非???,因此總體上看并沒有太大的區(qū)別。

話雖如此,我已經(jīng)看到V8團(tuán)隊(duì)成員推薦了此技巧,所以也許您確實(shí)希望有時(shí)嘗試遵循它。在可能的情況下遵循它不會(huì)對(duì)我造成任何傷害,但絕對(duì)不會(huì)以干凈的代碼和體系結(jié)構(gòu)決策為代價(jià)

概要

JS引擎中怎么在幕后工作

JS代碼必須在環(huán)境中運(yùn)行,最常見的是瀏覽器和Node.js。

該環(huán)境需要有一個(gè)引擎,該引擎需要采用以人類可讀的語法編寫的JS代碼,然后將其轉(zhuǎn)換為機(jī)器代碼。

引擎使用解析器逐行瀏覽代碼,并檢查語法是否正確。如果有任何錯(cuò)誤,代碼將停止執(zhí)行并引發(fā)錯(cuò)誤。

如果所有檢查都通過,則解析器將創(chuàng)建一個(gè)稱為抽象語法樹(AST)的樹數(shù)據(jù)結(jié)構(gòu)。

AST是一種數(shù)據(jù)結(jié)構(gòu),以樹狀結(jié)構(gòu)表示代碼。通過AST將代碼轉(zhuǎn)換為機(jī)器代碼更加容易。

然后,解釋器繼續(xù)進(jìn)行AST并將其轉(zhuǎn)換為IR,這是機(jī)器代碼的抽象,并且是JS代碼和機(jī)器代碼之間的中介。IR還可以執(zhí)行優(yōu)化,并且移動(dòng)性更強(qiáng)。

然后,JIT編譯器通過編譯代碼,獲取動(dòng)態(tài)反饋并使用該反饋改進(jìn)編譯過程,從而將生成的IR轉(zhuǎn)換為機(jī)器代碼。

以上是“JS引擎中怎么在幕后工作”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


文章標(biāo)題:JS引擎中怎么在幕后工作
URL鏈接:http://fisionsoft.com.cn/article/pdojei.html