摘要:前言是現(xiàn)在幾乎每個(gè)項(xiàng)目中必備的一個(gè)東西,但是其工作原理避不開(kāi)對(duì)的解析在生成的過(guò)程,有引擎,早期了項(xiàng)目,了解這個(gè)之前我們先來(lái)看看這種引擎解析出來(lái)是什么東西。
前言
babel是現(xiàn)在幾乎每個(gè)項(xiàng)目中必備的一個(gè)東西,但是其工作原理避不開(kāi)對(duì)js的解析在生成的過(guò)程,babel有引擎babylon,早期fork了項(xiàng)目acron,了解這個(gè)之前我們先來(lái)看看這種引擎解析出來(lái)是什么東西。不光是babel還有webpack等都是通過(guò)javascript parser將代碼轉(zhuǎn)化成抽象語(yǔ)法樹(shù),這棵樹(shù)定義了代碼本身,通過(guò)操作這顆樹(shù),可以精準(zhǔn)的定位到賦值語(yǔ)句、聲明語(yǔ)句和運(yùn)算語(yǔ)句
什么是抽象語(yǔ)法樹(shù)我們可以來(lái)看一個(gè)簡(jiǎn)單的例子:
var a = 1; var b = a + 1;
我們通過(guò)這個(gè)網(wǎng)站,他是一個(gè)esprima引擎的網(wǎng)站,十分好用.畫(huà)成流程圖如下:
而他的json對(duì)象格式是這樣的:
{ "type": "Program", "body": [ { "type": "VariableDeclaration", "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "a" }, "init": { "type": "Literal", "value": 1, "raw": "1" } } ], "kind": "var" }, { "type": "VariableDeclaration", "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "b" }, "init": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Identifier", "name": "a" }, "right": { "type": "Literal", "value": 1, "raw": "1" } } } ], "kind": "var" } ], "sourceType": "script" }眾多的引擎
chrome有v8,firefix有spidermonkey.還有一些常用的引擎有:
esprima
acron
Traceur
UglifyJS2
shift
下面是一些引擎的速度對(duì)比,以及用不同的框架,引擎?zhèn)兊募虞d速度:
我個(gè)人認(rèn)為,封裝的越完美的,其實(shí)解析的時(shí)間更長(zhǎng),引擎之間也是acron這個(gè)速度比較優(yōu)秀,babel引擎前身就是fork這個(gè)項(xiàng)目的。
AST的三板斧通過(guò)esprima生成AST
通過(guò)estraverse遍歷和更新AST
通過(guò)escodegen將AST重新生成源碼
我們可以來(lái)做一個(gè)簡(jiǎn)單的例子:
1.先新建一個(gè)test的工程目錄
2.在test工程下安裝esprima、estraverse、escodegen的npm模塊
npm i esprima estraverse escodegen --save
3.在目錄下面新建一個(gè)test.js文件,載入以下代碼:
const esprima = require("esprima"); let code = "const a = 1"; const ast = esprima.parseScript(code); console.log(ast);
你將會(huì)看到輸出結(jié)果:
Script { type: "Program", body: [ VariableDeclaration { type: "VariableDeclaration", declarations: [Array], kind: "const" } ], sourceType: "script" }
4.再在test文件中,載入以下代碼:
const estraverse = require("estraverse"); estraverse.traverse(ast, { enter: function (node) { node.kind = "var"; } }); console.log(ast);
輸出的結(jié)果:
Script { type: "Program", body: [ VariableDeclaration { type: "VariableDeclaration", declarations: [Array], kind: "var" } ], sourceType: "script" }
5.最后在test文件中,加入以下代碼:
const escodegen = require("escodegen"); const transformCode = escodegen.generate(ast) console.log(transformCode);
輸出的結(jié)果:
var a = 1;
通過(guò)這三板斧:我們將const a = 1轉(zhuǎn)化成了var a = 1
有沒(méi)有babel的感覺(jué)0.0
推薦網(wǎng)站esprima源碼
acron源碼
speed comparison
AST explorer
esprima可視化
在線可視化AST
抽象樹(shù)在前端用的很多很多,現(xiàn)在流行的工具,不管是webpack還是babel都會(huì)通過(guò)那個(gè)三板斧的流程,這里我只是大致介紹一下,過(guò)段時(shí)間,會(huì)出一篇抽象樹(shù)的語(yǔ)法,有興趣的也可以把esprima的源碼看一下,為什么是esprima呢,因?yàn)閑sprima的資料比較多,而acron比較輕量級(jí)。有興趣的可以關(guān)注一下我的[github](),記得點(diǎn)個(gè)star,就當(dāng)是對(duì)筆者的支持,謝謝。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92696.html
摘要:命令規(guī)定的是對(duì)外的接口,必須與模塊內(nèi)部的變量建立一一對(duì)應(yīng)關(guān)系。意思是導(dǎo)出的不是一個(gè)具體的數(shù)值,而是一個(gè)對(duì)象命令接受一對(duì)大括號(hào),里面指定要從其他模塊導(dǎo)入的變量名。大括號(hào)里面的變量名,必須與被導(dǎo)入模塊對(duì)外接口的名稱相同。 一、module.exports與exports nodeJS采用commonJs規(guī)范,當(dāng)前文件是一個(gè)模塊(module)私有域,通過(guò)exports屬性導(dǎo)出,通過(guò)re...
摘要:很多小白在看過(guò)很多教程之后仍然在敲代碼的時(shí)候不清楚應(yīng)該以什么樣的步驟進(jìn)行,那么這篇文章就一步一步分解整個(gè)過(guò)程,慢動(dòng)作回放讓大家看的清清楚楚明明白白。另外,中視圖部分最好單獨(dú)出來(lái),放在新建一個(gè)文件夾目錄下,并被名為引用,把其他邏輯部分放后者。 whay write this: 很多小白在看過(guò)很多教程之后仍然在敲代碼的時(shí)候不清楚應(yīng)該以什么樣的步驟進(jìn)行,那么這篇文章就一步一步分解整個(gè)過(guò)程,慢...
Javascript只有六個(gè)假值(用在條件if的判斷) showImg(https://segmentfault.com/img/bVLiHL?w=424&h=346); 全等于 類型不同,返回false類型相同,則 showImg(https://segmentfault.com/img/bVLiHS?w=476&h=341); 等于 類型相同:同上=== 類型不同:嘗試類型轉(zhuǎn)換==【不是真值和...
摘要:任務(wù)性質(zhì)不同的任務(wù)可以用不同規(guī)模的線程池分開(kāi)處理。線程池在運(yùn)行過(guò)程中已完成的任務(wù)數(shù)量。如等于線程池的最大大小,則表示線程池曾經(jīng)滿了。線程池的線程數(shù)量。獲取活動(dòng)的線程數(shù)。通過(guò)擴(kuò)展線程池進(jìn)行監(jiān)控??蚣馨ň€程池,,,,,,等。 Java線程池 [toc] 什么是線程池 線程池就是有N個(gè)子線程共同在運(yùn)行的線程組合。 舉個(gè)容易理解的例子:有個(gè)線程組合(即線程池,咱可以比喻為一個(gè)公司),里面有3...
摘要:首先一段代碼轉(zhuǎn)化成的抽象語(yǔ)法樹(shù)是一個(gè)對(duì)象,該對(duì)象會(huì)有一個(gè)頂級(jí)的屬性第二個(gè)屬性是是一個(gè)數(shù)組。最終完成整個(gè)文件依賴的處理。參考文章抽象語(yǔ)法樹(shù)一看就懂的抽象語(yǔ)法樹(shù)源碼所有的源碼已經(jīng)上傳 背景 隨著前端復(fù)雜度的不斷提升,誕生出很多打包工具,比如最先的grunt,gulp。到后來(lái)的webpack和 Parcel。但是目前很多腳手架工具,比如vue-cli已經(jīng)幫我們集成了一些構(gòu)建工具的使用。有的時(shí)...
閱讀 1225·2021-09-26 09:55
閱讀 3191·2019-08-30 15:55
閱讀 965·2019-08-30 15:53
閱讀 2296·2019-08-30 13:59
閱讀 2380·2019-08-29 13:08
閱讀 1107·2019-08-29 12:19
閱讀 3302·2019-08-26 13:41
閱讀 418·2019-08-26 13:24