我们先来通过工具【AST Explorer】看一段代码:
const add = (a,) => a + b;
代码对应的 json 数据:
{
"type": "Program",
"start": 0,
"end": 28,
"body": [
{
"type": "VariableDeclaration", // 变量声明
"start": 0,
"end": 28,
"declarations": [ // 具体声明
{
"type": "VariableDeclarator",
"start": 6,
"end": 27,
"id": {
"type": "Identifier", // 标识符
"start": 6,
"end": 9,
"name": "add" // 函数名
},
"init": {
"type": "ArrowFunctionExpression", // 箭头函数
"start": 12,
"end": 27,
"id": null,
"expression": true,
"generator": false,
"async": false,
"params": [ // 参数
{
"type": "Identifier",
"start": 13,
"end": 14,
"name": "a"
},
{
"type": "Identifier",
"start": 16,
"end": 17,
"name": "b"
}
],
"body": { // 函数体
"type": "BinaryExpression", // 二项式
"start": 22,
"end": 27,
"left": { // 二项式左边
"type": "Identifier",
"start": 22,
"end": 23,
"name": "a"
},
"operator": "+", // 二项式运算符
"right": { // 二项式右边
"type": "Identifier",
"start": 26,
"end": 27,
"name": "b"
}
}
}
}
],
"kind": "const"
}
],
"sourceType": "module"
}
也可以自己画一棵树https://resources.jointjs.com/demos/javascript-ast
就会生成一个树
概念
在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。(来自百科)
规范参考:【The ESTree Spec】
强力推荐阅读【the-super-tiny-compiler】
常见用途
- 代码语法、风格、的检查
- 代码的格式化、高亮、错误提示、自动补全
- 代码混淆压缩
-
UglifyJS2
(命令行工具,用于压缩 JavaScript 代码) - 优化变更代码,改变代码结构使达到想要的结构
- 代码打包工具
webpack、rollup
等等 -
CommonJS、AMD、CMD、UMD
等代码规范之间的转化 -
CoffeeScript、TypeScript、JSX
等转化为原生Javascript
图示过程
1、esprima :把源码转化为 AST。https://esprima.org/
pdf文档
Esprima is a high performance, standard-compliant ECMAScript parser written in ECMAScript (also popularly known as JavaScript).
Esprima can be used to perform lexical analysis (tokenization) or syntactic analysis (parsing) of a JavaScript program.
翻译:
Esprima是用ECMAScript(也称为JavaScript)编写的高性能,符合标准的ECMAScript解析器。
Esprima可用于执行JavaScript程序的词法分析(标记化)或语法分析(解析)。
A simple example on Node.js REPL:
var esprima = require('esprima');
var program = 'const answer = 42';
esprima.tokenize(program);
[ { type: 'Keyword', value: 'const' },
{ type: 'Identifier', value: 'answer' },
{ type: 'Punctuator', value: '=' },
{ type: 'Numeric', value: '42' } ]
esprima.parse(program);
{ type: 'Program',
body:
[ { type: 'VariableDeclaration',
declarations: [Object],
kind: 'const' } ],
sourceType: 'script' }
2、estraverse:遍历并更新 AST。https://github.com/estools/estraverse
Estraverse (estraverse) is ECMAScript traversal functions from esmangle project.
翻译:
Estraverse(estraverse)是esmangle项目中的ECMAScript遍历函数。
Example Usage:
The following code will output all variables declared at the root of a file.
estraverse.traverse(ast, {
enter: function (node,) {
if (node.type == 'FunctionExpression' || node.type == 'FunctionDeclaration')
return estraverse.VisitorOption.Skip;
},
leave: function (node,) {
if (node.type == 'VariableDeclarator')
console.log(node.id.name);
}
});
Usage:https://github.com/estools/estraverse/wiki/Usage
3、escodegen:将 AST 重新生成源码。https://github.com/estools/escodegen
Escodegen (escodegen) is an ECMAScript (also popularly known as JavaScript) code generator from Mozilla’s Parser API AST.
翻译:
Escodegen(escodegen)是Mozilla的Parser API AST的ECMAScript(也称为JavaScript)代码生成器。
npm install
Usage:
A simple example: the program:
escodegen.generate({
type: 'BinaryExpression',
operator: '+',
left: { type: 'Literal', value: 40 },
right: { type: 'Literal', value: 2 }
});
produces the string '40 + 2'
.