ESModule(ECMAScript Modules)是 JavaScript 的官方模块系统,其工作原理如下:
一、核心特性
1. 静态分析
- 模块依赖关系在代码执行前确定
import/export语句必须在顶层作用域- 不支持条件导入(除非使用动态导入)
javascript
// ✅ 合法的静态导入
import { foo } from './module.js';
// ❌ 不允许的(语法错误)
if (condition) {
import { foo } from './module.js';
}
2. 模块加载阶段
ESModule 加载分为三个主要阶段:
阶段1:解析(Parsing)
- 下载模块文件
- 解析为抽象语法树(AST)
- 识别所有
import和export语句 - 构建模块依赖图
阶段2:实例化(Instantiation)
- 创建模块作用域
- 在内存中为导出建立绑定(bindings)
- 建立导入和导出之间的连接(引用关系)
阶段3:求值(Evaluation)
- 执行模块代码
- 填充绑定的值
- 按照依赖顺序执行(深度优先)
二、关键机制
1. 实时绑定(Live Bindings)
- 导入的是对原始变量的引用,而不是值的拷贝
- 当导出值改变时,导入的值也会同步更新
javascript
// counter.js
export let count = 0;
export function increment() { count++; }
// main.js
import { count, increment } from './counter.js';
console.log(count); // 0
increment();
console.log(count); // 1 ⬅️ 自动更新
2. 严格模式
- ESModule 默认在严格模式下运行
- 顶层的
this是undefined
3. 循环依赖处理
- ESModule 支持循环引用
- 使用实时绑定机制解决循环依赖问题
javascript
// a.js
import { b } from './b.js';
export let a = 'a';
console.log(b); // 'b'
// b.js
import { a } from './a.js';
export let b = 'b';
console.log(a); // undefined(声明但未赋值)
三、浏览器中的工作流程
ESModule 的工作流程主要分为两个阶段:解析(Download & Parse)和执行(Execution)。
1. 解析入口文件
↓
2. 识别所有import语句
↓
3. 递归下载所有依赖模块
↓
4. 构建模块依赖图
↓
5. 实例化所有模块(建立绑定)
↓
6. 按依赖顺序执行代码
浏览器示例:
html
<!-- type="module" 启用 ESModule -->
<script type="module">
import { greet } from './greet.js';
greet('World');
</script>
四、Node.js 中的实现
Node.js 通过以下方式支持 ESModule:
1. 文件扩展名
.mjs文件被视为 ESModule- 或在
package.json中设置"type": "module"
2. 与 CommonJS 的区别
| 特性 | ESModule | CommonJS |
|---|---|---|
| 加载时机 | 静态,编译时 | 动态,运行时 |
| 导入方式 | import/export |
require/module.exports |
| 值类型 | 实时绑定 | 值拷贝 |
| 严格模式 | 默认启用 | 可选 |
| 顶层this | undefined |
当前模块 |
五、动态导入
javascript
// 运行时按需加载
async function loadModule() {
const module = await import('./dynamic-module.js');
module.doSomething();
}
// 条件导入
if (needsFeature) {
const { feature } = await import('./feature.js');
}
六、优势与限制
优势:
- 静态分析支持摇树优化(Tree-shaking)
- 更好的循环依赖处理
- 标准化,浏览器原生支持
- 异步加载能力
限制:
- 需要现代浏览器或 Node.js 支持
- 静态结构限制某些动态模式
- 与旧模块系统兼容需要额外处理
ESModule 的设计着重于可预测性 和优化潜力,通过静态分析和实时绑定等机制,提供了更可靠的模块化解决方案。