一、概念
AST 全称为 Abstract Syntax Tree,译为抽象语法树。在 JavaScript 中,任何一个对象(变量、函数、表达式等)都可以转化为一个抽象语法树的形式。抽象语法树本质就是一个树形结构的对象。
使用 astexplorer 可以在线将任意对象,表达式转换为 AST 语法树。
如果到这里你还是不太理解 AST 是什么东西。那么假设你的电脑主板坏掉了。维修人员的修理过程是:先把电脑各个零件拆开,找到坏掉的主板,检查主板是否还可以修好。如果不行,则换一个新的主板,再把电脑一步步重新组装好。那么 AST 就是被拆解的一个个电脑零件。
二、特点
一个对象生成 AST 的关键所在是词法分析和语法分析。
词法分析指的是将对象逐个扫描,获取每一个字母的信息,生成由对象组成的一维数组。
const a = 5;
//词法分析
[{value:'const',type:'keyword'},{value:'a',type:'identifier'}...]
语法分析指的是将有关联的对象整合成树形结构的表达形式。
const a = 5;
//语法分析
{
"type": "Program",
"start": 0,
"end": 12,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 12,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 11,
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"name": "a"
},
"init": {
"type": "Literal",
"start": 10,
"end": 11,
"value": 5,
"raw": "5"
}
}
],
"kind": "const"
}
],
"sourceType": "module"
}
三、用途
常用语各类转义、编译的插件中。比如最典型的 ES6 转换为 ES6 工具 、JSX 语法转换为 JavaScript 语法的 babel,代码规范工具 ESLint 以及各类 JS/CSS/HTML 压缩工具。
四、案例
现在,我们使用 AST 的概念来拆解一个最简单的函数。
function exp(a){return a}
使用 astexplorer 在线拆解得到结果如下:
- 在最外层的 type、start、end、body、sourceType 中,我们主要看中间 body 部分。把每一个 body 当成一个块来拆解。
- 第一个 body(块) 就是
function exp(a)
这段。这是一个 type 为 FunctionDeclaration (函数定义)类型的对象。每一个函数定义的块中都有一个 id 对象。如上所示,它的 id 对象信息中 type 为 Identifier,name 为exp
。它不是表达式,也不是异步。所以 express、generator、async 皆为 false。最后它有一个参数 params 对象集,在该参数对象集中参数名 name 为a
。 - 再看第二个 body(块) 就是
return a
。这是一个 type 为 BlockStatement (块语句)类型的对象。在其内部有一个 type 为 ReturnStatement (返回语句)类型的语句。在返回的 argument 集合中参数名 name 为形参a
。 - 可以看到上面的拆解中,每一个块都有 type、start、end、body 这几个字段。
其中 type 表达当前块的类型。比如 FunctionDeclaration 表示函数定义,Identifier 表示标识符、BlockStatement 表示块语句、ReturnStatement 表示返回语句等。
start 表示该块开始的位置,end 表示该块结束的位置,body 表示子块。
其他的字段根据块的性质不同有所不同。