现有 初始JS代码如下
var s=92
var a = s+5
var b=func(1324801, a)
希望得到的结果是
var s = 92
var a = 97
var b = func(1324901,97)
做之前的思考: 首先是遍历节点,但是要遍历哪种类型的节点呢,然后把节点的值计算出来,最后进行节点的替换。
完整的代码为:
// 替换已经定义的变量
//babel库及文件模块导入
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generator = require("@babel/generator").default;
const fs = require('fs');
// 读取文件
let encode_file = fs.readFileSync("./text.js", {
encoding: "utf-8"
});
// 转换为ast数
let ast = parser.parse(encode_file);
const visitor =
{
"Identifier|BinaryExpression"(path){
let {confident,value} = path.evaluate();
if (confident){
path.replaceInline(types.valueToNode(value))
}
}
};
// 调用插件,处理源代码
traverse(ast, visitor);
//生成新的 js code,并且保存到文件中输出
let {code} = generator(ast,opts = {jsescOption:{"minimal":true}});
fs.writeFile('text_after.js', code, (err) => {
});
代码解释:
(1)选择需要便利的节点
遍历 Identifier(标识符节点,例如声明变量时 var a = 3 的a) 或者 BinaryExpression(二进制表达式 通常指运算,例如 1+2)
(2) 进行节点的值计算
path.evaluate() 是计算表达式的值,没有参数,就是计算这个节点的值,会返回两个值,当第一个值为true的时候,第二个值就是计算的结果
(3)进行节点的值的替换
path.replaceInline() 为节点的替换. 在进行节点的替换时,必须先构造节点才可以替换。说白了,就是JSON结构的数据,如果是字面量,可以直接用 valueToNode方法来直接进行构造,如果是其他节点,可以对照在线解析网站进行构造,注意各个子节点的顺序。所以默认格式为 path.replaceInline(types.valueToNode(value)) 来进行替换
本文的知识点:
- 如何同时遍历多种类型的节点, 节点名|节点名
- 计算表达式的值 使用函数 path.evaluate(),不需要传入参数,返回两个值,当第一个值为true时,第二个值为计算出来的值。
- 如何进行节点的值的替换 使用path.replacelnline(types.valueToNode(value)) 进行替换。