在使用前端許多工具插件的時候,咱們大多知道每一個工具庫、每一個插件能作什麼,不過不少同窗其實並不清楚背後用到的技術,如webpack、rollup、UglifyJS、Lint等不少的工具和庫的核心都是經過Abstract Syntax Tree 抽象語法樹這個概念來實現對代碼的檢查、分析等操做的。經過了解抽象語法樹這個概念,你也能夠隨手編寫相似的工具,發現一個新的世界。javascript
理論的知識老是有些枯燥乏味,不過客官別急,一步一步來。html
其實這些工具的原理都是經過JavaScript Parser把代碼轉化爲一顆抽象語法樹(AST),這顆樹定義了代碼的結構,經過操縱這顆樹,咱們能夠精準的定位到聲明語句、賦值語句、運算語句等等,實現對代碼的分析、優化、變動等操做。前端
In computer science, an abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract syntactic structure of source code written in a programming language.java
在計算機科學中,抽象語法樹(abstract syntax tree或者縮寫爲AST),或者語法樹(syntax tree),是源代碼的抽象語法結構的樹狀表現形式,這裏特指編程語言的源代碼。node
Javascript的語法是爲了給開發者更好的編程而設計的,可是不適合程序的理解。因此須要轉化爲AST來更適合程序分析,瀏覽器編譯器通常會把源碼轉化爲AST來進行進一步的分析等其餘操做。webpack
好比說有一段代碼:web
var a = 3;
a + 5;
複製代碼
那麼它的抽象語法樹就相似:
express
JavaScript Parser, 把js源碼轉化爲抽象語法樹的解析器。編程
瀏覽器會把js源碼經過解析器轉爲抽象語法樹,再進一步轉化爲字節碼或直接生成機器碼。瀏覽器
通常來講每一個js引擎都會有本身的抽象語法樹格式,Chrome的v8引擎,firefox的SpiderMonkey引擎等等,MDN提供了詳細SpiderMonkey AST format的詳細說明,算是業界的標準。
發展到如今可能不一樣的JavaScript Parser的AST格式會不一樣,或基於SpiderMonkey AST format,或從新設計本身的AST format,或基於SpiderMonkey AST format優化改進。經過優化抽象語法樹,來使程序運行的更快,也是一種提升效率的方法。
Esprima
UglifyJS2
Traceur
Acorn
Shift
複製代碼
在Esprima的官網有一個比較各個Parser解析速度的列表Speed Comparison。 看下來Acorn是公認的最快的。
UglifyJS2的做者本身實現了一套js的抽象語法樹,用到了繼承,和現有的扁平的抽象語法樹都有所不一樣,但做者也提供使用不一樣的抽象語法樹來解析代碼。
AST explorer能夠在線看到不一樣的parser解析js代碼後獲得的AST。
JavaScript AST visualizer 能夠在線可視化的看到AST。
生成並使用抽象語法樹 經過 esprima , 把一個名字爲ast的空函數的源碼生成一顆AST樹:
var esprima = require('esprima');
var code = 'function ast(){}';
var ast = esprima.parse(code);
複製代碼
生成的抽象語法樹長這樣:
"type": "Program",
"body": [
{
"type": "FunctionDeclaration",
"id": {
"type": "Identifier",
"name": "ast",
"range": [
9,
12
]
},
"params": [],
"body": {
"type": "BlockStatement",
"body": [],
"range": [
14,
16
]
},
"generator": false,
"expression": false,
"range": [
0,
16
]
}
],
"sourceType": "module",
"range": [
0,
16
]
}
複製代碼
經過 estraverse 遍歷而且更新抽象語法樹,把函數名稱改成ast_awsome:
...
var estraverse = require('estraverse');
estraverse.traverse(ast, {
enter: function (node) {
node.name += "_awsome";
}
});
複製代碼
經過 escodegen 將AST從新生成爲源碼:
...
var escodegen = require("escodegen");
var regenerated_code = escodegen.parse(ast)
複製代碼
經過 esprima 把源碼轉化爲AST 經過 estraverse 遍歷並更新AST 經過 escodegen 將AST從新生成源碼 抽象語法樹的用途 瀏覽器最早就會把源碼解析爲抽象語法樹,對瀏覽器而言AST的做用很是重要。
對開發者而言,AST的做用就是能夠精準的定位到代碼的任何地方,它就像是是你的手術刀,對代碼進行一系列的操做。
代碼語法的檢查、代碼風格的檢查、代碼的格式化、代碼的高亮、代碼錯誤提示、代碼自動補全等等 如JSLint、JSHint對代碼錯誤或風格的檢查,發現一些潛在的錯誤 IDE的錯誤提示、格式化、高亮、自動補全等等 代碼混淆壓縮 UglifyJS2等 優化變動代碼,改變代碼結構使達到想要的結構 代碼打包工具webpack、rollup等等 CommonJS、AMD、CMD、UMD等代碼規範之間的轉化 CoffeeScript、TypeScript、JSX等轉化爲原生Javascript 總結 抽象語法樹在前端領域中的應用普遍,經過抽象語法樹你們能夠實現不少功能,發現編寫工具提升效率帶來的樂趣。
Abstract syntax tree
Understanding ASTs by Building Your Own Babel Plugin
UglifyJS — why not switching to SpiderMonkey AST
A Technical Comparison of the Shift and SpiderMonkey AST Formats
SpiderMonkey Parser API
轉載自 div.io/topic/1994?…, 感謝原做者