之前碰到有混淆的代码,都是依靠别人写好的插件,能不能还原听天由命
如果要冲高级工程师的话,AST是必备的一项技能,刚好现在有空,就花时间来研究一番……
参考资料:
环境准备:
- AST 在线解析网站:https://astexplorer.net/

纯白色实在太过亮眼了,官方没有提供模式切换,不过这里有DIY方案,效果如下:

- 安装babel功能包:npm install @babel/core @babel/parser @babel/traverse @babel/generator @babel/types
解析代码 -> 语法树(parser)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | const fs = require("fs");
 const code1 = fs.readFileSync('code.js', 'utf-8');
 
 const parser = require("@babel/parser");
 const code2 = "const name = 'cxs';";
 
 
 const ast = parser.parse(code2, {sourceType: "module"})
 console.log(ast)
 
 | 
语法树 -> 生成代码(generator)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | const parser = require("@babel/parser");const generator = require("@babel/generator").default;
 
 const code2 = "const name = 'cxs';";
 const ast = parser.parse(code2, {sourceType: "module"})
 
 
 ast.program.body[0].declarations[0].id.name = "age";
 ast.program.body[0].declarations[0].init.value = 25;
 const result = generator(ast)
 console.log(result.code);
 
 >>> const age = 25;
 
 | 

遍历节点(traverse)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | const parser = require("@babel/parser");const generate = require("@babel/generator").default
 const traverse = require("@babel/traverse").default
 
 const code = `
 const name = "";
 const age = 0;
 console.log(xxx);
 `
 const ast = parser.parse(code)
 
 
 const visitor = {
 NumericLiteral(path){
 path.node.value = 25
 },
 StringLiteral(path){
 path.node.value = "cxs"
 },
 CallExpression(path){
 path.remove()
 }
 }
 
 traverse(ast, visitor)
 const result = generate(ast)
 console.log(result.code)
 
 `
 输出:
 const name = "cxs";
 const age = 25;
 `
 
 | 
构造新节点(types)
对照 AST网站 和 函数的使用说明,倒序的方式构造节点
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | const parser = require("@babel/parser");const generate = require("@babel/generator").default;
 const traverse = require("@babel/traverse").default;
 const types = require("@babel/types");
 
 const code = `
 const name = "cxs";
 `
 const ast = parser.parse(code)
 
 const visitor = {
 VariableDeclaration(path){
 let id = types.identifier("age");
 let init = types.numericLiteral(25);
 let declarator = types.variableDeclarator(id, init);
 let declaration = types.variableDeclaration("const", [declarator]);
 path.insertAfter(declaration);
 path.stop();
 }
 }
 
 traverse(ast, visitor)
 const result = generate(ast)
 console.log(result.code)
 
 `
 const name = "cxs";
 const age = 25;
 `
 
 | 
进入和退出节点(enter / exit)
