JavaScript 模块化主要靠 ES6 模块(ESM)和 CommonJS(CJS):ESM 静态编译时解析、import/export 语法、只读绑定、默认严格模式;CJS 动态运行时加载、require/module.exports、对象引用、支持动态路径;二者加载时机、循环依赖处理及 Node 互操作方式不同,需注意兼容性与转换。

JavaScript 实现模块化主要靠 ES6 模块(ECMAScript Modules,简称 ESM) 和 CommonJS(CJS) 两种标准。它们在语法、加载时机、运行环境和设计哲学上存在本质差异,不能直接混用,需注意兼容性与转换处理。
ES6 模块:静态、编译时解析
ES6 模块使用 import / export 语法,特点是 静态结构 ——导入导出语句必须位于顶层作用域,不能写在条件或函数内; 浏览器 和现代 Node.js(v12+ 默认启用)原生支持。
- 导出方式灵活:可默认导出(
export default)或命名导出(export const a = 1、export {a, b}) - 导入是只读绑定:导入的变量与源模块保持实时绑定(如导出的是对象,修改其属性会影响源模块)
- 自动严格模式:ESM 脚本默认启用 strict mode,无需手动声明
- 顶层
this为undefined,不指向全局对象
CommonJS:动态、运行时加载
CommonJS 是 Node.js 早期采用的模块规范,使用 require() 和 module.exports,特点是 动态执行——可以在任意位置调用 require,支持条件加载、循环依赖等运行时行为。
- 导出即对象引用:每次
require返回的是module.exports的浅拷贝(实际是缓存引用),多次require同一模块返回同一对象 - 支持动态路径:如
require('./' + name + '.js'),ES6 不允许 - 顶层
this指向module.exports,可直接赋值:this.a = 1
关键差异对比
以下几点最易引发问题:
立即学习“Java 免费学习笔记(深入)”;
- 加载时机:CJS 是运行时同步加载;ESM 是编译时静态分析 + 异步加载(即使同步写法,底层也按依赖图预解析)
- 循环依赖处理:CJS 返回当前已执行部分的
exports对象(可能不完整);ESM 创建“实时绑定”,即使模块未执行完,也能访问已声明的导出绑定 - Node.js 中的互操作:Node 允许 ES 模块
importCJS 模块(自动包装为默认导出),但 CJS 的require无法直接加载 ESM 文件(会报错),除非用dynamic import()或转成 CJS - 文件扩展名与配置:Node 中
.mjs强制为 ESM,.cjs强制为 CJS;.js则由package.json的"type": "module"决定
如何选择与共存
新项目推荐优先使用 ES6 模块,尤其面向浏览器或现代 Node 环境;遗留项目或需动态加载逻辑时,CommonJS 仍有实用价值。






























