美文网首页Typescript
Babel 编译器执行原理浅解

Babel 编译器执行原理浅解

作者: 再见地平线_e930 | 来源:发表于2021-05-11 16:43 被阅读0次
    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 编译器执行原理浅解

        本文链接:https://www.haomeiwen.com/subject/ywfndltx.html