JavaScript代碼是如何被機器理解并執(zhí)行的呢?
作為 JavaScript? 開發(fā)者,通常我們不需要關心JavaScript引擎是如何執(zhí)行代碼的。但是晶府,了解 JavaScript 引擎的工作原理,知曉它如何處理我們編寫的 JS? 代碼钻趋、肯定是有益的川陆。
注意:這篇文章講述的原理,基于 Node.js 和 Chromium 的瀏覽器所使用的 V8 引擎蛮位。
HTML 解析器遇到script標簽時较沪,會從網(wǎng)絡鳞绕、緩存中以字節(jié)流的方式加載代碼。此階段尸曼,字節(jié)流解碼器會負責將字節(jié)轉(zhuǎn)為代碼字符们何。
例如,字節(jié)流中的 0066? 解碼為 f控轿,0075 解碼為 u冤竹,006e 解碼為 n,0063 解碼為 c茬射,0074 解碼為 t鹦蠕,0069 解碼為 i,006f 解碼為? o在抛,006e 解碼為 n钟病。結合起來便是: function! JavaScript? 中的一個函數(shù)關鍵字刚梭,這時會將它做為JavaScript代碼肠阱,并創(chuàng)建一個標記并發(fā)送給JS引擎。
JS引擎使用兩個解析器:預解析器和解析器朴读。為了減少加載網(wǎng)頁所需的時間辖所,引擎會盡量避免立即解析不必要的代碼。預解析器處理可能稍后會使用的代碼磨德,而解析器則處理立即需要的代碼!
如果某個函數(shù)只有在用戶點擊按鈕后才會被調(diào)用吆视,那么不必要立即編譯這段代典挑。如果用戶最終點擊了按鈕并需要那段代碼,它才會被發(fā)送到解析器啦吧。
解析器根據(jù)從字節(jié)流解碼器接收到的代碼創(chuàng)建節(jié)點:創(chuàng)建一個抽象語法樹(AST)您觉。
接下來,輪到解釋器了授滓!解釋器遍歷 AST琳水,并根據(jù) AST 包含的信息生成字節(jié)碼。
一旦字節(jié)碼完全生成般堆,AST 就會被刪除在孝,從而釋放內(nèi)存空間。字節(jié)碼已經(jīng)是機器可以識別和處理的東西淮摔!
字節(jié)碼速度很快私沮。
但還可以更快。當字節(jié)碼運行時和橙,它可以檢測某些行為是否經(jīng)常發(fā)生仔燕,比如你多次調(diào)用一個函數(shù):這時便可優(yōu)化它造垛,讓它運行得更快:字節(jié)碼與行為反饋數(shù)據(jù)一起被發(fā)送到優(yōu)化編譯器。優(yōu)化編譯器接從這些信息中生成高度優(yōu)化過的字節(jié)碼:機器碼晰搀。
總結而言五辽,JS代碼變?yōu)闄C器可識別的整個過程是:
字節(jié)流 → JavaScript代碼 → 抽象語法樹(AST) → 字節(jié)碼 → 機器碼。