语法差异
- CommonJS:通过
require()
方法引入模块,使用 module.exports
或 exports
导出模块。例如:
// 引入模块
const math = require('./math.js');
// 导出模块
module.exports.add = function(a, b) {
return a + b;
};
- ES6 模块:使用
import
关键字引入模块,export
关键字导出模块。例如:
// 导出模块
export function add(a, b) {
return a + b;
};
// 引入模块
import {add} from './math.js';
加载机制差异
- CommonJS:模块是运行时加载,即当
require()
执行时才会去加载模块并执行模块代码,且是同步加载。在服务器端,文件都在本地,这种同步加载影响不大。但在浏览器环境下,同步加载可能会阻塞页面渲染。
- ES6 模块:是编译时加载,在代码解析阶段就确定了模块的依赖关系。在浏览器中,ES6 模块默认是异步加载,不会阻塞页面渲染。
作用域差异
- CommonJS:每个模块都有自己独立的作用域,通过
exports
或 module.exports
导出的内容在外部模块引用时是值的拷贝(对于基本数据类型),对于对象类型是引用传递。
- ES6 模块:同样具有独立作用域,通过
export
导出的内容在导入模块中是实时绑定的,即如果导出的值在原模块中发生变化,导入模块中对应的值也会改变。
适用场景
- 优先选择 CommonJS 规范的场景:
- Node.js 服务器端项目:Node.js 对 CommonJS 规范原生支持,在服务器端文件加载通常不存在阻塞问题,并且许多现有的 Node.js 第三方库都是基于 CommonJS 规范编写的,使用 CommonJS 规范能更好地与这些库集成。
- 对兼容性要求较高的项目:在一些不支持 ES6 模块的旧环境中,如早期版本的 Node.js 或某些不支持 ES6 模块的 JavaScript 运行环境,只能使用 CommonJS 规范。
- 优先选择 ES6 模块规范的场景:
- 现代浏览器端项目:ES6 模块在浏览器中支持异步加载,适合构建大型前端应用,不会阻塞页面渲染,提高用户体验。同时,配合打包工具(如 Webpack),能更好地进行代码拆分和优化。
- 追求代码静态分析和优化的项目:由于 ES6 模块是编译时加载,便于进行静态分析,像 Tree - shaking 这样的优化技术可以去除未使用的代码,减小打包后的文件体积。