前端ast
什么是抽象语法树
抽象语法树 Abstract Syntax Tree 简称AST,是源代码语法结构的一种抽象表示。
比如 const a = 123;
,用ast可以表示为
ast json表示为
{
"type": "Program",
"start": 0,
"end": 14,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 14,
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 13,
"id": {
"type": "Identifier",
"start": 6,
"end": 7,
"name": "a"
},
"init": {
"type": "Literal",
"start": 10,
"end": 13,
"value": 123,
"raw": "123"
}
}
],
"kind": "const"
}
],
"sourceType": "module"
}
你也可以在ast explorer上试试!
在代码语法的检查、代码风格的检查、格式化、高亮、错误提示、自动补全、实现一套代码适配多端运行等等,即优化变更代码,改变代码结构使达到想要的结构都需要用到ast。
webpack、Lint等这些工具的原理都是通过 js解析器(Js Parser) 把源代码转化为一颗抽象语法树(AST),通过操纵这颗树,我们可以精准的定位到声明语句、赋值语句、运算语句等等,实现对代码的分析、优化、变更等操作。
另外Ast是有规范的,不可能随心所欲的去写,这是里规范: estree。
js解析器
想想看 如果你想将源码转为ast,你不会每次都跑去ast explorer上,获取吧。
所以就有专门的工具来获取ast,这就是js解析器。
Js解析器的作用,把Js源码转化为抽象语法树。
Js解析器并不一定都是js写的,有可能是c或者python,如:Js解析器.exe、Js解析器.py
常见的JS解析器有哪些?
acorn、babel/parser、uglify-js、 Esprima、espree等等。这里有更详细的介绍
浏览器中执行js
除了webpack、esLint等这些工具会用到ast外,浏览器引擎(如v8)执行到js的时候 也需要ast
- 当浏览器引擎拿到 js源码时,会将其转为 ast 树
- 将构建完毕的 ast 树转为字节码(注意浏览器只会将当前调用栈的代码转为字节码)
- 字节码转为机器码执行
参考 这里
自己利用ast优化代码
为了兼容低版本浏览器 我们也通常会使用 babel 打包编译我们的代码将 ES6 语法降低版本,
比如箭头函数变成普通函数、将 const、let 声明改成 var 等等,
它们也都是通过 AST 来完成的,只不过实现的过程比较复杂和精致。
不过也都是这三板斧:
import { parse } from "@babel/parser";
import generate from "@babel/generator";
import traverse from "@babel/traverse";
// 将源代码转为ast
const ast = parse("const a = 123;");
// 修改ast
traverse.default(ast, {
VariableDeclaration(path) {
if (path.node.kind === "const") {
path.node.kind = "var";
}
},
});
// 将修改后的ast转换回代码
const output = generate.default(ast);
console.log(output.code); // var a = 123;