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);
网友评论