JavaScript 编译与解释执行
JavaScript 是一门即时编译(JIT)语言,代码执行经历解析、编译、执行三个阶段。
编译型 vs 解释型
对比
| 类型 | 执行方式 | 代表语言 | 特点 |
|---|---|---|---|
| 编译型 | 源码 → 机器码 → 执行 | C/C++、Go | 执行快,编译慢 |
| 解释型 | 源码 → 逐行解释执行 | Python | 启动快,执行慢 |
| JIT编译型 | 源码 → 字节码 → 机器码 | JavaScript、Java | 平衡启动与执行效率 |
JavaScript 执行流程
三阶段模型
JavaScript
源代码 → 解析(Parser) → AST → 解释执行(Interpreter) → 字节码
↓
热点代码编译(Compiler) → 机器码
1. 词法分析(Lexical Analysis)
将源代码拆分为 Token 流。
JavaScript
const a = 1 + 2;
// Token 流
[
{ type: 'Keyword', value: 'const' },
{ type: 'Identifier', value: 'a' },
{ type: 'Punctuator', value: '=' },
{ type: 'Numeric', value: '1' },
{ type: 'Punctuator', value: '+' },
{ type: 'Numeric', value: '2' },
{ type: 'Punctuator', value: ';' }
]
2. 语法分析(Syntax Analysis)
将 Token 流转换为抽象语法树(AST)。
JavaScript
const a = 1 + 2;
// AST 结构(简化)
{
type: 'VariableDeclaration',
kind: 'const',
declarations: [{
type: 'VariableDeclarator',
id: { type: 'Identifier', name: 'a' },
init: {
type: 'BinaryExpression',
operator: '+',
left: { type: 'Literal', value: 1 },
right: { type: 'Literal', value: 2 }
}
}]
}
3. 解释执行
生成字节码并执行。
JavaScript
// V8 字节码示例(简化)
Ldar a // 加载变量 a
Star r0 // 存储到寄存器
Add r0, [1] // 加法操作
编译优化策略
提前编译(AoT)
JavaScript
// 函数声明会提前编译
function declared() {
return 'I am compiled early';
}
// 函数表达式运行时编译
const expressed = function() {
return 'I am compiled at runtime';
};
作用域确定
JavaScript
// 编译阶段确定作用域
var x = 1;
function foo() {
console.log(x); // 编译时已知访问外部 x
var x = 2;
}
foo(); // undefined(变量提升)
V8 执行管道
JavaScript
┌─────────────┐
│ Parser │ 解析源码生成 AST
└──────┬──────┘
↓
┌─────────────┐
│ Interpreter │ 生成字节码执行
│ (Ignition)│
└──────┬──────┘
↓
┌─────────────┐
│ Compiler │ 热点代码优化编译
│ (TurboFan) │
└─────────────┘
Ignition 解释器
- 快速生成字节码
- 低内存占用
- 适合冷启动代码
TurboFan 编译器
- 优化热点代码
- 生成高效机器码
- 基于类型反馈优化
同一段代码可能同时存在字节码和机器码两个版本,优化后切换执行。
编译时 vs 运行时
编译时(提前错误检测)
text
// 语法错误 - 编译时发现
function foo( {
// SyntaxError: Unexpected token
}
// 作用域错误 - 编译时确定
function bar() {
console.log(undeclaredVar); // ReferenceError(运行时)
}
运行时(动态特性)
text
// 动态类型 - 运行时确定
let value = 42;
value = 'now a string'; // 运行时类型变化
// 动态属性 - 运行时添加
const obj = {};
obj.newProp = 'added'; // 运行时扩展
要点总结
| 阶段 | 工作 | 输出 |
|---|---|---|
| 词法分析 | 拆分 Token | Token 流 |
| 语法分析 | 构建语法树 | AST |
| 解释执行 | 生成字节码 | 字节码 |
| JIT 编译 | 优化热点代码 | 机器码 |
- JavaScript 是 JIT 编译语言
- 源码 → Token → AST → 字节码 → 机器码
- V8 使用 Ignition 解释器 + TurboFan 编译器
- 编译时确定作用域,运行时确定值
📝 发现内容有误?点击此处直接编辑