js引擎的工作原理,js是怎樣處理事件的eventloop,宏任務源tasks和微任務源jobs分別有哪些?js是如何構造抽象語法書(AST)的?

js引擎只執行同步任務, 異步任務會有工作線程來執行,當需要進行異步操作(定時器、ajax請求、dom事件註冊等), 主線程會發一個異步任務的請求, 相應的工作線程接受請求; 當工作線程完成工作之後, 通知主線程;主線程接收到通知之後, 會執行一定的操作(回調函數)。主線程和工作線程之間的通知機制叫做事件循環。

調用棧 (call stack): 主線程執行時生成的調用棧
任務隊列 (task queue): 工作線程完成任務後會把消息推到一個任務隊列, 消息就是註冊時的回調函數
在這裏插入圖片描述

當調用棧爲空時, 主線程會從任務隊列裏取一條消息並放入當前的調用棧當中執行, 主線程會一直重複這個動作直到消息隊列爲空。 這個過程就叫做事件循環 (event-loop)。

關於宏任務和微任務,參考 事件流、事件模型、事件循環概念理解? 瀏覽器線程理解與microtask與macrotask

ES6新引入了Promise標準,同時瀏覽器實現上多了一個microtask微任務概念。在ECMAScript中,microtask稱爲jobs,macrotask可稱爲task。

macrotask宏任務tasks,也就是上面說到的任務隊列的任務。執行棧上的每個任務都屬於宏任務,主線程執行完執行棧的任務,從任務隊列取新的任務。宏任務執行時不會中斷,會一次性執行完,爲了及時渲染數據,主線程執行完一個宏任務之後,會執行一次渲染。
task–》渲染 --》宏任務 --》渲染 …

microtask微任務jobs,可以看成是插隊需要及時處理的任務,會在當前主線程task任務執行後,渲染線程渲染之前,執行完當前積累所有的微任務。
task–》jobs --》渲染 --》宏任務 --》jobs --》渲染 …

AST 參考:程序語言進階之DSL與AST實戰解析

將抽象語法樹之前要先了解下NLP中文法的概率。任何一種語言,具體說就是DSL,都有自己的一套文法,用來表示這套語言的邏輯規範。不同的文法寫出來的語法表達式也不一樣。我們根據語法表達式來解析語言,就可以形成一個AST抽象語法樹。然後可以作進一步處理。我常用的是PEG解析表達式語法。可以很輕鬆的寫出語法的每一條產生式規則,來構造生成AST。所謂AST可以理解成按照一定語法結構組成的詞彙流,每個詞彙有特定的語法含義,比如說這是一個聲明,這個一個操作符等等。
在這裏插入圖片描述

上面這個圖是蘋果最早做的KHTML渲染引擎中的KJS(javascript引擎),他是基於AST來實現的JavaScript語言解析的,先通過詞法分析得到JSTokens流,然後經過語法分析得到抽象語法樹,然後經過字節碼生成器,轉換成字節碼。字節碼經過JavaScript虛擬機JIT編譯成機器碼,然後執行。這是最初的設計架構,後來蘋果公司基於此重構出了webkit渲染引擎,google基於webkit單獨維護,稱爲blink渲染引擎,chrome的JS引擎改造爲V8引擎。參考:簡述Chromium, CEF, Webkit, JavaScriptCore, V8, Blink

舉個例子常用的babel插件的原理就是基於babylon詞法語法分析器生成抽象語法樹,將代碼文本轉換成按照特定語法組合的token流集合,然後經過babtlon-traverse這個組件來負責處理遍歷語法樹,訪問每個token節點,通過對token的處理,可以生成我們需要的AST語法樹,然後再通過babylon-generator這個組件來做代碼生成,根據AST生成代碼。比如可以將 箭頭函數 轉換成 function函數。

瀏覽器中,通過開發者調試工具分析就能看到,下載完js腳本後,首先瀏覽器要先解析代碼=》初始化上下文環境=》執行代碼,整個是evaluate script的過程,解析代碼的過程也是編譯js的過程所以看最前面第一步就是compile script,將js代碼編譯成字節碼(這一塊涉及到瀏覽器js引擎的優化,v8引擎是編譯成字節碼,後面經過JIT解析執行(這個參考 你不知道的LLVM編譯器 可以提升效率做動態優化), 這個類似於java、C#這些需要將源代碼編譯成中間語言,然後在虛擬機執行,javascript編譯成字節碼後面也是在虛擬機執行),然後就開始執行腳本。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章