我们先来通过工具【AST Explorer】看一段代码:
const add = (a, b) => 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, parent) { if (node.type == 'FunctionExpression' || node.type == 'FunctionDeclaration') return estraverse.VisitorOption.Skip; }, leave: function (node, parent) { 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 escodegen
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'
.