Open yygmind opened 4 years ago
babel 在处理一个节点时,是以访问者的形式获取节点的信息,并进行相关的操作,这种操作是通过visitor对象实现的。
在 visitor 中定义了处理不同节点的函数。
visitor: {
Program: {
enter(path, state) {
console.log('start processing this module...');
},
exit(path, state) {
console.log('end processing this module!');
}
},
ImportDeclaration:{
enter(path, state) {
console.log('start processing ImportDeclaration...');
// do something
},
exit(path, state) {
console.log('end processing ImportDeclaration!');
// do something
}
}
}
esprima、estraverse 和 escodegen 模块是操作 AST 的三个重要模块,也是实现 babel 的核心依赖。
例如:语法转换插件需要借助 babel-core 和 babel-types 两个模块,就是依赖 esprima、estraverse 和 escodegen
每一个含有type属性的对象,我们称之为节点,修改是指获取对应的类型并修改改节点的属性即可;
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "answer"
},
"init": {
"type": "BinaryExpression",
"operator": "*",
"left": {
"type": "Literal",
"value": 6,
"raw": "6"
},
"right": {
"type": "Literal",
"value": 7,
"raw": "7"
}
}
}
],
"kind": "var"
}
],
"sourceType": "script"
}
查看遍历过程:
const esprima = require("esprima");
const estraverse = require("estraverse");
let code = "var answer=6 * 7";
// 遍历语法树
estraverse.traverse(esprima.parseScript(code), {
enter(node) {
console.log("enter", node.type);
},
leave(node) {
console.log("leave", node.type);
}
});
const esprima = require("esprima");
const estraverse = require("estraverse");
const escodegen= require("escodegen");
let code = "var answer=6 * 7";
let tree=esprima.parseScript(code); // 生成语法树
// 遍历语法树
estraverse.traverse(tree, {
enter(node) {
console.log("enter", node.type);
// 修改变量名
if(node.type==='VariableDeclarator'){
node.id.name='result';
}
},
leave(node) {
console.log("leave", node.type);
}
});
// 编译修改后的语法树;
let compileTreeJS=escodegen.generate(tree);
console.log(compileTreeJS);
打印结果如下 :
var result=6 * 7
通过工具了解抽象语法树在 JavaScript 中的体现以及在 NodeJS 中用于生成、遍历和修改 AST 抽象语法树的核心依赖;让我们有了更加深刻地认识;
大致分为下面四步:
具体见下方链接文件的代码: