- 作者:陈大鱼头
- github: KRISACHAN
开发息息相关
虽然 Babel 团队在各种哭穷,但是 Babel 始终是我们前端在开发中不可或缺的重要工具。
虽然我们只是 API 调用工,但是多了解一些总是会有好处的嘛 ☄️☄️☄️
什么是编译器?
编译器(compiler)是一种计算机程序,它会将某种编程语言写成的源代码(原始语言)转换成另一种编程语言(目标语言)。
源代码(source code)→ 预处理器(preprocessor)→ 编译器(compiler)→ 汇编程序(assembler)→ 目标代码(object code)→ 链接器(linker)→ 可执行文件(executables),最后打包好的文件就可以给电脑去判读运行了。
什么是解释器?
解释器(英语:interpreter),是一种计算机程序,能够把解释型语言解释执行。解释器就像一位“中间人”。解释器边解释边执行,因此依赖于解释器的程序运行速度比较缓慢。解释器的好处是它不需要重新编译整个程序,从而减轻了每次程序更新后编译的负担。相对的编译器一次性将所有源代码编译成二进制文件,执行时无需依赖编译器或其他额外的程序。
跟编译器的区别就是一个是边编译边执行,一个是编译完才执行。
高级语言编译器步骤
- 输入源程序字符流
- 词法分析
- 语法分析
- 语义分析
- 中间代码生成
- 机器无关代码优化
- 代码生成
- 机器相关代码优化
- 目标代码生成
V8 编译 JS 代码的过程
- 生成抽象语法树(AST)和执行上下文
- 第一阶段是分词(tokenize),又称为词法分析
- 第二阶段是解析(parse),又称为语法分析
- 生成字节码
- 字节码就是介于 AST 和机器码之间的一种代码。但是与特定类型的机器码无关,字节码需要通过解释器将其转换为机器码后才能执行。
- 执行代码
JS 执行代码的过程
- 执行全局代码时,创建全局上下文
- 调用函数时,创建函数上下文
- 使用 eval 函数时,创建 eval 上下文
- 执行局部代码时,创建局部上下文
关于 Babel
Babel ,又名 Babel.js。 是一个用于 web 开发,且自由开源的 JavaScript 编译器、转译器。
Babel 的编译流程:
Parse
Babel 的第一步就是将源码转换为抽象语法树(AST)
const babel = require('@babel/core');
const {
parseAsync } = babel;
const parseCode = async (code = '', options = {
}) => {
const res = await parseAsync(code, options);
};
parseCode(`
const a = 1;
`)
可通过 https://astexplorer.net/ 在线查看具体结果
这一步会将收集到的的代码,通过 词法分析(Lexical analysis) 跟 语法分析(Parsing) 两个阶段将代码转换成 AST
词法分析(Lexical analysis)
词法分析会将代码转为 token ,可以理解为是对每个不可分割单词元的描述,例如 const
就会转换成下面这样:
Token {
type:
TokenType {
label: 'const',
keyword: 'const',
beforeExpr: false,
startsExpr: false,
rightAssociative: false,
isLoop: false,
isAssign: false,
prefix: false,
postfix: false,
binop: null,
updateContext: null
},
value: 'const',
start: 5,
end: 10,
loc:
SourceLocation {
start: Position {
line: 2, column: 4 },
end: Position {
line: 2, column: 9 },
filename: undefined,
identifierName: undefined
}
}
type
就是 对 token 的描述,如果想要查看 bebal 生成的 token,我们可以在 options
里写入:
parserOpts: {
tokens: true
}
关于 @babel/parser
更多配置,可查看:https://babeljs.io/docs/en/babel-parser#options
语法分析(Parsing)
语法分析则是将上述的 token 转换成对应的 ast 结构
所以我们就可以看到这样的一段树状结构(过滤部分信息)
{
"type": "VariableDeclaration",
"start": 0,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 14
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 6,
"end": 13,
"loc": {
"start": {
"line": 1,
"column": 6
},
"end": {