前言
babel是現在幾乎每個專案中必備的一個東西,但是其工作原理避不開對js的解析在生成的過程,babel有引擎babylon,早期fork了專案acron,瞭解這個之前我們先來看看這種引擎解析出來是什麼東西。不光是babel還有webpack等都是通過javascript parser將程式碼轉化成抽象語法樹,這棵樹定義了程式碼本身,通過操作這顆樹,可以精準的定位到賦值語句、宣告語句和運算語句。有興趣的可以關注一下我的github,點一個star。謝謝
什麼是抽象語法樹
我們可以來看一個簡單的例子:
var a = 1;
var b = a + 1;
複製程式碼
我們通過這個網站,他是一個esprima引擎的網站,十分好用.畫成流程圖如下:
而他的json物件格式是這樣的:
{
"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
下面是一些引擎的速度對比,以及用不同的框架,引擎們的載入速度:
我個人認為,封裝的越完美的,其實解析的時間更長,引擎之間也是acron這個速度比較優秀,babel引擎前身就是fork這個專案的。
AST的三板斧
- 通過esprima生成AST
- 通過estraverse遍歷和更新AST
- 通過escodegen將AST重新生成原始碼
我們可以來做一個簡單的例子:
1.先新建一個test的工程目錄 2.在test工程下安裝esprima、estraverse、escodegen的npm模組
npm i esprima estraverse escodegen --save
複製程式碼
3.在目錄下面新建一個test.js檔案,載入以下程式碼:
const esprima = require('esprima');
let code = 'const a = 1';
const ast = esprima.parseScript(code);
console.log(ast);
複製程式碼
你將會看到輸出結果:
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);
複製程式碼
輸出的結果:
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);
複製程式碼
輸出的結果:
var a = 1;
複製程式碼
- 通過這三板斧:我們將
const a = 1
轉化成了var a = 1
有沒有babel的感覺0.0
推薦網站
總結
抽象樹在前端用的很多很多,現在流行的工具,不管是webpack還是babel都會通過那個三板斧的流程,這裡我只是大致介紹一下,過段時間,會出一篇抽象樹的語法,有興趣的也可以把esprima的原始碼看一下,為什麼是esprima呢,因為esprima的資料比較多,而acron比較輕量級。有興趣的可以關注一下我的github,記得點個star,就當是對筆者的支援,謝謝。