掌握es modules关键在于理解运行机制:导出导入时机、作用域边界、环境适配;import/export是编译时静态声明,支持活绑定;可组合默认与命名导出;动态import()实现按需加载;跨环境需注意后缀、type属性及package.json配置。

掌握 ES Modules 的高级进阶技巧,关键不在背语法,而在理解模块系统的运行机制和工程场景中的真实约束。重点是搞清“导出导入的时机”“作用域边界”“与运行环境的适配”,而不是堆砌用法。
理解静态分析本质,避开动态赋值陷阱
ESM 的 import/export 是编译时静态声明,不是运行时赋值。这意味着:
- 不能在 if、for 或函数内部写 export 或 import —— 会直接报语法错误
- export const PI = 3.14 是绑定值;但 export let count = 0 后续修改 count,其他模块看到的是更新后的值(活绑定,live binding)
- 不能用 export { foo } from './bar' 动态拼接路径;路径必须是字符串字面量
灵活组合默认导出 + 命名导出
一个模块可同时提供默认导出(主功能)和命名导出(辅助工具),提升 API 可读性:
- 导出:export default class ApiClient { ... }; export const TIMEOUT = 5000; export function retry() { ... }
- 导入:import ApiClient, { TIMEOUT, retry } from './api.js'
- 避免只用默认导出导致命名随意(如 import utils from './utils'),也避免只用命名导出导致调用冗长(如 import { format, parse, validate } from './validator')
善用动态导入 import() 实现按需加载
import() 返回 Promise,适合做条件加载、路由懒加载或插件化扩展:
- 根据用户权限加载不同模块:if (user.role === 'admin') { const adminTools = await import('./admin-tools.js'); adminTools.init(); }
- 配合 try/catch 处理模块缺失:try { const chart = await import('chart.js'); chart.render(); } catch (e) { console.warn('图表模块未加载'); }
- 注意:动态导入的模块仍遵循 ESM 规则,其内部的 export/import 不受动态影响
跨环境兼容:Node.js 与浏览器双支持
同一套 ESM 代码想在 Node 和浏览器都跑通,需注意三点:
- Node 中启用 ESM:要么用 .mjs 后缀,要么在 package.json 加 "type": "module"
- 浏览器中 script 标签必须加 type="module":<script type="module" src="./main.js"></script>
- 路径必须带扩展名(如 './utils.js'),浏览器不支持自动补 .js;Node 在 module 模式下也要求显式后缀











