Babel 编译器执行原理浅解

Babel 一般用来把 ES6 以后的 JavaScript 代码转换为 ES5,增加兼容性,是浏览器可以运行
我们可以把 Babel 看作一个编译器,它编译代码的流程大概如下:
babel编译流程图
举个例子,有这样一段 JS 代码需要转换:
const name = "zsn";
const foo = (name) => console.log(name);
foo(name);
1.如流程图图所示,搜先进行词法分析,则上面代码中的每个单词和符号都会被提取出来,最终组成 tokens 数组如下:
[
    {
        "type": "Keyword", // Keyword表示时 javascript 中的关键字
        "value": "const"
    },
    {
        "type": "Identifier", // Identifier表示是标识符,这里的 foo用来标识是一个函数
        "value": "foo"
    },
    {
        "type": "Punctuator", // 表示是一个符号
        "value": "="
    },
    {
        "type": "Punctuator",
        "value": "("
    },
    {
        "type": "Identifier",
        "value": "name"
    },
    {
        "type": "Punctuator",
        "value": ")"
    },
    {
        "type": "Punctuator",
        "value": "=>"
    },
    {
        "type": "Identifier",
        "value": "console"
    },
    {
        "type": "Punctuator",
        "value": "."
    },
    {
        "type": "Identifier",
        "value": "log"
    },
    {
        "type": "Punctuator",
        "value": "("
    },
    {
        "type": "Identifier",
        "value": "name"
    },
    {
        "type": "Punctuator",
        "value": ")"
    },
    {
        "type": "Punctuator",
        "value": ";"
    },
    {
        "type": "Identifier",
        "value": "foo"
    },
    {
        "type": "Punctuator",
        "value": "("
    },
    {
        "type": "String",
        "value": "\"zsn\""
    },
    {
        "type": "Punctuator",
        "value": ")"
    },
    {
        "type": "Punctuator",
        "value": ";"
    }
]
2.接下来对 tokens 数组进行语法分析,组成一颗旧的抽象语法树,如图:
旧的抽象语法树
{
  "type": "Program",
  "body": [
    {
      "type": "VariableDeclaration",
      "declarations": [
        {
          "type": "VariableDeclarator",
          "id": {
            "type": "Identifier",
            "name": "foo"
          },
          "init": {
            "type": "ArrowFunctionExpression",
            "id": null,
            "params": [
              {
                "type": "Identifier",
                "name": "name"
              }
            ],
            "body": {
              "type": "CallExpression",
              "callee": {
                "type": "MemberExpression",
                "computed": false,
                "object": {
                  "type": "Identifier",
                  "name": "console"
                },
                "property": {
                  "type": "Identifier",
                  "name": "log"
                }
              },
              "arguments": [
                {
                  "type": "Identifier",
                  "name": "name"
                }
              ]
            },
            "generator": false,
            "expression": true,
            "async": false
          }
        }
      ],
      "kind": "const"
    },
    {
      "type": "ExpressionStatement",
      "expression": {
        "type": "CallExpression",
        "callee": {
          "type": "Identifier",
          "name": "foo"
        },
        "arguments": [
          {
            "type": "Literal",
            "value": "zsn",
            "raw": "\"zsn\""
          }
        ]
      }
    }
  ],
  "sourceType": "script"
}
3.对该树进行深度优先遍历,遍历树的每一个节点,并对节点使用 Babel 对应的插件进行处理,如遍历到 'const' 节点时就把 'const' 通过插件转换为 'var'。
这样对每一个节点遍历下来,就生成了一棵新的抽象语法树
新的抽象语法
{
  "type": "Program",
  "body": [
    {
      "type": "VariableDeclaration",
      "declarations": [
        {
          "type": "VariableDeclarator",
          "id": {
            "type": "Identifier",
            "name": "foo"
          },
          "init": {
            "type": "FunctionExpression",
            "id": {
              "type": "Identifier",
              "name": "foo"
            },
            "params": [
              {
                "type": "Identifier",
                "name": "name"
              }
            ],
            "body": {
              "type": "BlockStatement",
              "body": [
                {
                  "type": "ReturnStatement",
                  "argument": {
                    "type": "CallExpression",
                    "callee": {
                      "type": "MemberExpression",
                      "computed": false,
                      "object": {
                        "type": "Identifier",
                        "name": "console"
                      },
                      "property": {
                        "type": "Identifier",
                        "name": "log" 
                      }
                    },
                    "arguments": [
                      {
                        "type": "Identifier",
                        "name": "name"
                      }
                    ]
                  }
                }
              ]
            },
            "generator": false,
            "expression": false,
            "async": false
          }
        }
      ],
      "kind": "var" // 这里 const => var
    },
    {
      "type": "ExpressionStatement",
      "expression": {
        "type": "CallExpression",
        "callee": {
          "type": "Identifier",
          "name": "foo"
        },
        "arguments": [
          {
            "type": "Literal",
            "value": "zsn",
            "raw": "\"zsn\""
          }
        ]
      }
    }
  ],
  "sourceType": "script"
}
4.最后进行代码生成,生成目标代码
"use strict";

var name = "zsn";

var foo = function foo(name) {
  return console.log(name);
};

foo(name);

你可能感兴趣的:(Babel 编译器执行原理浅解)