乐趣区

关于babel:babel-与-ast

什么是 babel

Babel 是一个工具链,次要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便可能运行在以后和旧版本的浏览器或其余环境中。

什么是形象语法树(AST)

在计算机科学中,形象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种形象示意。它以树状的模式体现编程语言的语法结构,树上的每个节点都示意源代码中的一种构造。之所以说语法是“形象”的,是因为这里的语法并不会示意出实在语法中呈现的每个细节。
对于 AST 的相干介绍:
举荐的介绍链接:
Leveling Up One’s Parsing Game With ASTs
中文翻译: https://segmentfault.com/a/11…

维基百科里的介绍: https://en.wikipedia.org/wiki…

babel 的简略应用

相干 api 能够参考文档: https://babeljs.io/docs/en/ba…
应用 babel 的 API 将代码解析成 ast:

var babel = require("@babel/core");
const code = `const a = 1 + 2;`
// code 解析成 ast
const result = babel.transformSync(code, {ast: true});
console.log(result.ast)

当然 ast 也能够转换成代码:

const {code} = babel.transformFromAstSync(result.ast, { presets: ["minify"], babelrc: false, configFile: false,});
console.log(code)

在这个在线网站, 你能够更加间接地看到 code 和 ast 的比拟:
https://lihautan.com/babel-as…
const n = 1 的 ast:

-program:Program{sourceType:"module" -body:[ -VariableDeclaration { -declarations:[ -VariableDeclarator{ -id:Identifier{ name:"n"} -init:NumericLiteral{-extra:{ rawValue:1 raw:"1"} value:1 } } ] kind:"const" } ] directives:[]}

babel 插件:

var babel = require("@babel/core");
const code = 'const n = 1';
const output = babel.transformSync(code, {plugins: [ function myCustomPlugin() {
 return {
 visitor: {Identifier(path) {// 在这个例子里咱们将所有变量 `n` 变为 `x` if (path.isIdentifier({ name: 'n'})) {path.node.name = 'x';}
 },
 },
 };
 },
 ],});
console.log(output.code);
// const x = 1;

通过 babel 的插件咱们能够对代码进行随心所以的批改
对于 visitor 应用的是访问者模式, 在遍历阶段,babel 会先进行深度优先遍从来拜访 AST 的每一个节点。你能够为拜访指定一个回调函数,而后每当拜访某个节点的时候,babel 会调用这个函数,并给函数传入以后拜访的节点。

当初咱们增加另一个函数: NumericLiteral, 在刚刚的 ast 中咱们能够看到 const n = 1 是有 NumericLiteral 此节点的

function myCustomPlugin() {
 return {
 visitor: {Identifier(path) {console.log('identifier');
 },
 NumericLiteral(path) {console.log('NumericLiteral');
 },
 },
 };
}

运行 plugin.js, 打印后果:

Identifier
NumericLiteral
const x = 1;

即在碰到此节点的时候 就会触发插件中对应节点的回调, 对于回调函数的 path 能够在此文档中查看: https://github.com/jamiebuild…

批改表达式

在插件办法 NumericLiteral 上增加操作:

visitor: {// 省略其余办法 NumericLiteral(path) {console.log('NumericLiteral');
 const newNode = babel.types.binaryExpression('+', babel.types.NumericLiteral(path.node.value), babel.types.NumericLiteral(10));
 path.replaceWith(newNode);
 path.skip(); // 因为咱们新减少了一个 NumericLiteral, 所以插件会检测到, 并且又会触发此回调, 造成有限循环 // skip 的作用就是跳过对以后门路子节点的拜访}
}

这里咱们新建了一个 binaryExpression, 将 const x = 1 转换为 const x = 1 + 10
这是对于 babel.types 的文件: https://www.babeljs.cn/docs/b…
本文代码记录: https://github.com/Grewer/JsD…

参考资料

https://lihautan.com/step-by-…

退出移动版