解锁 JavaScript 模块的秘密:ES6模块内部结构详解
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
随着 JavaScript 向现代化发展,模块化编程成为大型项目的基石。ES6 引入了原生模块系统(ES Modules, ESM),为开发者提供了更加高效、规范和可优化的模块管理方式。 本文将系统讲解 ES6 模块的核心机制,并重点介绍 一、ES6 模块核心特性1. 静态结构(Static Structure)ES6 模块在 编译阶段 即确定模块依赖,便于构建工具进行优化(如 Tree-shaking)。
相比之下,CommonJS 使用 2. 模块作用域隔离每个模块都有自己的作用域,定义的变量不会污染全局,也不会影响其他模块。 3. 导出方式:命名导出与默认导出
二、模块加载机制简析1. 浏览器中:
2. Node.js 中:
三、模块对象结构解析当你使用
1. 模块对象的特点:
2. 示例:live binding 的效果
四、如何遍历模块对象你可以使用
或:
输出:
五、 |
属性 | 浏览器支持 | Node.js 支持 | 说明 |
---|---|---|---|
import.meta.url | ✅ | ✅ | 模块绝对路径(file:// 格式) |
import.meta.env | 🔶 | ❌(除构建工具注入) | 构建工具(如 Vite)注入环境变量 |
// Vite 自动注入
if (import.meta.env.DEV) {
console.log('开发模式');
}
对象 | 来源 | 内容说明 |
---|---|---|
模块对象 | import * as mod | 包含导出成员的引用 |
import.meta | 特殊关键字 | 提供当前模块的元信息,如 URL、环境变量等 |
import()
:动态导入模块import('./math.js').then(mod => {
console.log(mod.sum(2, 3));
});
特点:
await
在模块中允许在顶层使用 await
(无需函数封装):
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
⚠️ 仅适用于 ESM 模块,不支持普通 <script>
脚本。
ES6 模块支持循环引用,但不建议过度依赖。
// a.js
import { b } from './b.js';
export const a = 'A';
console.log('from b:', b);
// b.js
import { a } from './a.js';
export const b = 'B';
console.log('from a:', a);
循环引用的变量可能为 undefined
,ESM 会保证模块执行顺序正确,但需谨慎使用。
// math.js
export const PI = 3.14;
export const add = (a, b) => a + b;
export default 'Math Module';
// main.js
import * as math from './math.js';
console.log('模块对象属性:');
for (const [k, v] of Object.entries(math)) {
console.log(` ${k}:`, v);
}
console.log('\nimport.meta 信息:');
console.log(` 当前模块 URL: ${import.meta.url}`);
项目 | 说明 |
---|---|
模块对象 | import * as mod 获取到的对象,包含所有导出成员 |
import.meta | 模块级元信息,如 URL、环境变量等 |
Live Binding | 导入的是绑定引用,值是“活的”,会跟随原模块更新 |
默认导出 | 对应 mod.default 属性 |
动态导入与懒加载 | 使用 import() 动态加载模块 |
顶层 await | 在模块最外层使用 await ,更灵活地处理异步逻辑 |
转自https://juejin.cn/post/7532425297150427171