babel 怎么把字符串解析成 AST,是怎么进行词法/语法分析的?#前端面试
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
定义 - Babel 是我们知道的将 ES6、ES7等代码转译为 ES5 代码且能安全稳定运行最好的工具 - 同时它允许开发者开发插件,能够在编译时期转换 JavaScript 的结构。
Babel概述 我们需要知道 3 个 Babel 处理流程中的重要工具; 1. 解析
转换
babel-traverse 模块允许你浏览、分析和修改抽象语法树(AST Abstract Syntax Tree)
** Babel 中重要的对象Vistor** 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
        }
    }
}
 
定义 - AST (Abstract Syntax Tree)是抽象语法树英文的缩写,AST语法树每一层都拥有相同的结构,这样的每一层结构也被叫做节点(Node)。 - AST 是源代码的抽象语法结构树状表现形式,Webpack、ESLint、JSX、TypeScript 的编译和模块化规则之间的转化都是通过 AST 来实现对代码的检查、分析以及编译等操作。 - 一个 AST 可以由单一的节点或是成百上千个节点构成。 它们组合在一起可以描述用于静态分析的程序语法。 Javascript 语法的AST(抽象语法树) javascript 语句要想知道抽象语法树之后的代码是什么,里面的字段都代表什么含义以及遍历的规则,可以通过javascript语法转换AST工具来实现javascript语法的在线转换; 例如: 
 - 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" 
}```  
**estraverse 遍历和修改AST**
查看遍历过程:

 
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); } });
 - 打印结果如下:

- 以上代码通过estraverse模块的traverse方法,将esprima模块装换的AST进行了遍历。
- 通过打印type属性,可以知道深度遍历AST就是遍历每一层的type属性,所以遍历会分为两个阶段,进入阶段和离开阶段,在traverse方法中分别用参数enter和leave两个函数监听;
**escodegen 将 AST 转换成 JS**

