抽象语法树(Abstract Syntax Tree)

  1. webpack 和 Lint 等很多的工具和库的核心都是通过 Abstract Syntax Tree 抽象语法树这个概念来实现对代码的检查、分析等操作的;
  2. 通过了解抽象语法树这个概念,可以随手编写类似的工具;

抽象语法树用途

  1. 代码语法的检查、代码风格的检查、代码的格式化、代码的高亮、代码错误提示、代码自动补全等等
    • 如 JSLint、JSHint 对代码错误或风格的检查,发现一些潜在的错误;
    • IDE 的错误提示、格式化、高亮、自动补全等等;
  2. 代码混淆压缩
    • UglifyJS2 等;
  3. 优化变更代码,改变代码结构使达到想要的结构
    • 代码打包工具 webpack、rollup 等等;
    • CommonJS、AMD、CMD、UMD 等代码规范之间的转化;
    • CoffeeScript、TypeScript、JSX 等转化为原生 Javascript;

抽象语法树定义

  1. 在计算机科学中,抽象语法树(abstract syntax tree 或者缩写为 AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码;
  2. Javascript 的语法是为了给开发者更好的编程而设计的,但是不适合程序的理解。所以需要转化为 AST 来使之更适合程序分析,浏览器编译器一般会把源码转化为 AST 来进行进一步的分析等其他操作;

JavaScript Parser

  1. JavaScript Parser 把 js 源码转化为抽象语法树的解析器;
  2. 浏览器会把 js 源码通过解析器转为抽象语法树,再进一步转化为字节码或直接生成机器码;
  3. 一般来说每个 js 引擎都会有自己的抽象语法树格式,Chrome 的 v8 引擎,firefox 的 SpiderMonkey 引擎等等,MDN 提供了详细 SpiderMonkey AST format 的详细说明,算是业界的标准;

常用的 JavaScript Parser

  1. esprima
  2. traceur
  3. acorn
  4. shift

esprima

  1. AST的可视化工具
  2. 示例代码:
    let esprima = require('esprima'); // 把源代码转成抽象语法树
    let estraverse = require('estraverse'); // 遍历并更新 AST
    let escodegen = require('escodegen'); // 将 AST 重新生成源码
    
    let sourceCode = `function ast(){}`; // 源代码就是 ascii 字符串
    let ast = esprima.parse(sourceCode);
    // console.log(ast);
    
    /**
    * 遍历语法树 遍历的方式采用的深度的方式
    * 遍历的时候只遍历有 type 属性的节点
    * 如果一个节点遍历完成,它同时有儿子和弟弟,如果先遍历弟弟,就是广度,如果先遍历儿子再遍历弟弟就是深度
    */
    let indent = 0; // 缩进几个空格
    const padding = () => " ".repeat(indent);
    estraverse.traverse(ast, {
      enter(node) {
        // 在遍历语法树的时候可以对它进行转换
        console.log(padding() + '进入' + node.type);
        if (node.type === 'FunctionDeclaration') {
          node.id.name = 'new' + node.id.name;
        }
        indent += 4;
      },
      leave(node) {
        indent -= 4;
        console.log(padding() + '离开' + node.type);
      }
    });
    /*
    进入Program
        进入FunctionDeclaration
            进入Identifier
            离开Identifier
            进入BlockStatement
            离开BlockStatement
        离开FunctionDeclaration
    离开Program
    */
    
    let targetCode = escodegen.generate(ast);
    console.log(targetCode); // function newast() {}
    

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于产品、设计、开发的问题和看法,还有技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程

了解更多

目录

  1. 1. 抽象语法树(Abstract Syntax Tree)
  2. 2. 抽象语法树用途
  3. 3. 抽象语法树定义
  4. 4. JavaScript Parser
    1. 4.1. 常用的 JavaScript Parser
    2. 4.2. esprima