<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          瀏覽器如何運(yùn)行一段JavaScript代碼

          共 2381字,需瀏覽 5分鐘

           ·

          2024-04-11 01:14

          開篇

          JavaScript在我們?nèi)粘i_發(fā)中扮演著至關(guān)重要的角色,大部分時(shí)間都與它打交道,因此對這門語言的了解再多也不為過。

          雖然有很多關(guān)于JavaScript的書籍和資料,但絕大多數(shù)都從JavaScript語言本身的角度去分析其語法和語義,很少有與JavaScript具體執(zhí)行過程相關(guān)的分析資料。因此,我邀請大家一起從瀏覽器的角度來看一下一段JavaScript代碼到底是如何執(zhí)行的。

          以 Google 瀏覽器為例,JavaScript 代碼由 V8 引擎負(fù)責(zé)解釋執(zhí)行。代碼的執(zhí)行總體上經(jīng)歷以下三個(gè)步驟:

          1. 將代碼解析為抽象語法樹(AST)并創(chuàng)建執(zhí)行上下文
          2. 根據(jù) AST 生成字節(jié)碼作為中間代碼
          3. 解釋器 Ignition 會逐條解釋執(zhí)行代碼

          整個(gè)流程圖如下:

          e097ed920336f7bd0cc03d132628b694.webp

          生成AST

          為什么要將代碼解析成AST呢,直接用原代碼不行嗎?

          答案肯定是不行,因?yàn)闉g覽器并不能理解我們所寫的代碼。這個(gè)理由就像將html需要解析為DOM一樣,瀏覽器并不能理解我們所編寫的代碼,需要將我們寫的代碼編譯成瀏覽器能夠理解的結(jié)構(gòu),也就是AST。

          AST是一種非常重要的數(shù)據(jù)結(jié)構(gòu),許多著名的項(xiàng)目都在使用它。

          比如Babel,Babel被用于代碼轉(zhuǎn)換,將es6的代碼轉(zhuǎn)換為es5的代碼,用于解決兼容性問題,Babel的工作原理就是將es6源碼解析為AST,再將es6的AST轉(zhuǎn)化為es5的AST,最后利用es5的AST生成源碼。

          類似的還有ESlint,ESlint是用來檢查js代碼規(guī)范的插件,它的檢查流程也是將源碼解析成AST,再利用AST來檢查代碼的規(guī)范問題。

          將源碼解析成AST通常需要兩個(gè)步驟:

          一、詞法分析

          詞法分析又稱為分詞(tokenize),是將一行行代碼拆分為一個(gè)個(gè)token。如下圖:

          3783e64387dc503ba098432c7257c12a.webp

          二、語法分析

          語法分析又稱解析,將上一步生成的token數(shù)據(jù)根據(jù)語法規(guī)則轉(zhuǎn)化為AST。在轉(zhuǎn)化過程中,如果不符合語法規(guī)則,會終止轉(zhuǎn)化并拋出一個(gè)語法錯(cuò)誤。轉(zhuǎn)化成的AST如下圖:

          7eb3c4410dabb99ad092c3df0d597563.webp

          可以通過 AST可視化網(wǎng)站:https://astexplorer.net/  來體驗(yàn)成生成AST。

          除了生成AST,該階段還會創(chuàng)建代碼塊的執(zhí)行上下文。其實(shí)上述的編譯過程都發(fā)生在v8引擎內(nèi)部,對于我們開發(fā)者來說完全是黑盒的,但是執(zhí)行上下文這個(gè)概念卻是至關(guān)重要的,因?yàn)樗谴a運(yùn)行的基本環(huán)境。

          生成字節(jié)碼

          生成AST后,接著解釋器 Ignition 就會將AST轉(zhuǎn)化為字節(jié)碼并解釋執(zhí)行字節(jié)碼。

          為什么又要將AST解析成字節(jié)碼呢,上文不是說過瀏覽器可以理解AST嗎?答案是解決內(nèi)存占用的問題。

          其實(shí)一開始v8引擎并不會將AST轉(zhuǎn)化為字節(jié)碼,而是直接將AST轉(zhuǎn)化為機(jī)器碼并執(zhí)行。雖然執(zhí)行效率特別高,但是同時(shí)暴露出來了嚴(yán)重的內(nèi)存占用問題。因?yàn)関8引擎要消耗大量的內(nèi)存來存放轉(zhuǎn)化后的機(jī)器碼。為了解決內(nèi)存占用的問題,v8團(tuán)隊(duì)引入了字節(jié)碼,花了大量的時(shí)間,完成了當(dāng)前的這套架構(gòu)。

          解釋下字節(jié)碼是什么,字節(jié)碼是介于AST和機(jī)器碼之間的一種代碼,字節(jié)碼需要解釋器將其轉(zhuǎn)化為機(jī)器碼之后才能執(zhí)行。為了更好的去理解字節(jié)碼,下面是源碼、字節(jié)碼、機(jī)器碼的一個(gè)對比圖:

          b0b0b33e4f0f7bf60423e1a2c1995899.webp

          可以看出,字節(jié)碼對比機(jī)器碼占用的空間要小得多。所以使用字節(jié)碼可以減少系統(tǒng)的內(nèi)存使用。

          執(zhí)行代碼

          對于一段第一次被執(zhí)行的字節(jié)碼,解釋器 Ignition 會逐條解釋并執(zhí)行。在執(zhí)行的過程中,如果發(fā)現(xiàn)熱點(diǎn)代碼(Hotspot),比如說一段被重復(fù)執(zhí)行多次的代碼,后臺的 編譯器 TurboFan 就會將該段熱點(diǎn)字節(jié)碼編譯成機(jī)器碼并保存起,當(dāng)下次在執(zhí)行到該段熱點(diǎn)代碼時(shí),只需要執(zhí)行編譯后的機(jī)器碼就行,這樣就節(jié)提升了大量的執(zhí)行效率。執(zhí)行流程如下圖所示:

          518a30a99a0fd0a49fa08fd2cf307cac.webp

          這種字節(jié)碼配合解釋器和編譯器的技術(shù)正是最近很火的技術(shù)————即時(shí)編譯(JIT)

          總結(jié)

          至此本文分析完了 JavaScript 代碼執(zhí)行的整個(gè)階段。在宏觀角度上 JavaScript 代碼會經(jīng)歷如下步驟:

          1. 解析器將 JavaScript 代碼解析(詞法分析、語法分析)成AST并創(chuàng)建執(zhí)行上下文
          2. 解釋器 Ignition 將AST轉(zhuǎn)化為字節(jié)碼
          3. 解釋器 Ignition 對字節(jié)碼逐條解釋執(zhí)行
          • 如果發(fā)現(xiàn)熱點(diǎn)代碼(HotSpot),后臺編譯器 TurboFan 會將熱點(diǎn)代碼編譯成機(jī)器碼并保存,進(jìn)而提升執(zhí)行效率。

          整個(gè)JavaScript代碼執(zhí)行是慢啟動,越執(zhí)行越快。這種字節(jié)碼配合解釋器和編譯器的技術(shù)叫做即時(shí)編譯(JIT)。v8引擎也是基于這種技術(shù)來實(shí)現(xiàn)對內(nèi)存占用和執(zhí)行效率的調(diào)控

          最后在JavaScript代碼執(zhí)行過程中,最重要的部分就是執(zhí)行上下文了,它是代碼運(yùn)行時(shí)的基本環(huán)境。

          bf12d87ea456021e361ef2aed6a291ae.webp

          參考鏈接

          • 瀏覽器工作原理與實(shí)踐:https://blog.poetries.top/browser-working-principle/guide/part2/lesson07.html#%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87-hoisting

          • How JavaScript Works:https://www.freecodecamp.org/news/javascript-under-the-hood-v8/

          更多推薦


          瀏覽 35
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美亚州性爱 | 色婷婷免费在线 | 欧美成人做爰高潮片免费看贝隆尼 | 美女被操到喷水 | 久久久国产视频 |