AST(抽象语法树)是对JS代码抽象语法结构的表示,Babel可以帮我们把代码解析成AST,方便我们进行转换,操作,生成。社区的 eslint,代码转换工具 taro 等,都离不开 AST 进行操作。下面整理下 AST 常见的使用方法。
创建 AST
Babel 提供了 @babel/parser
的 parse
方法进行代码字符串解析,可以创建 AST 对象。
const parser = require('@babel/parser');
const code = `const a = 5;`;
const ast = parser.parse(code, { sourceType: "module" });
遍历 AST
有了 AST 对象之后,就可以使用 @babel/traverse
库进行遍历,该库方便我们在不同类型节点进行操作。
比如我们要把代码 const a = 5;
中的 a 替换成 b,可以这样操作:
const traverse = require('@babel/traverse').default;
traverse(ast, {
Identifier(path) {
// 替换name
path.node.name = 'b';
}
});
或者 const a = 1 + 2;
替换成 const a = 3;
const traverse = require('@babel/traverse').default;
const t = require('@babel/types');
traverse(ast, {
BinaryExpression(path) {
// 替换name
path.replaceWith(t.numericLiteral(3));
}
});
生成新的代码
有了修改后的 AST 对象,我们可以使用 @babel/generator
库生成新的代码。
const generator = require('@babel/generator').default;
const { code } = generator(ast);
console.log(code); // const a = 3;
下面是完整的代码示例
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generator = require('@babel/generator').default;
const code = 'const a = 5;';
const ast = parser.parse(code, { sourceType: 'module' });
traverse(ast, {
Identifier(path) {
// 替换name
path.node.name = 'b';
}
});
const { code: output } = generator(ast);
console.log(output); // const b = 5;
我们也可以自己通过 @babel/template
创建模板字符串生成代码,通过占位符来注入动态变量。
const proxyAst = template.ast(
`
new Proxy($0, {
get: function(target, key) {
return target[key] || 0;
}
})
`,
{
placeholderPattern: /^\$\d+/,
preserveComments: true
}
);
const objectStr = 'People';
proxyAst.expression.arguments[0].name = objectStr;
const ProxyCode = generator(proxyAst).code;
console.log(ProxyCode); // new Proxy(People, { get: function(target, key) { return target[key] || 0; } })