CommonJS 的 `module.exports` (以及 `exports`) 和 ES6 的 `export` 对比

特性CommonJS (module.exports, exports)ES6 (export)
语法module.exports = ...export const/let/var name = ...;
exports.name = ...export function myFunc() { ... }
const myVar = ...; module.exports = myVar;export { name1, name2 as alias, ... };
module.exports = { name: ..., func: ... };export default someValue;
导出类型导出一个可以是任何值的单一对象可以导出多个命名的绑定 (live bindings) 和一个默认导出
导入语法const module = require('./module');import { name1, alias } from './module';
const { name } = require('./module');import * as module from './module';
import defaultExport from './module';
import './module'; (仅执行模块代码)
加载时机运行时加载 (动态)编译时加载 (静态)
静态分析不易进行静态分析支持静态分析,便于 Tree Shaking
循环依赖处理可能出现问题,加载部分导出或错误更好地处理循环依赖
适用环境主要用于 Node.js 环境现代浏览器和 Node.js (需配置或 .mjs 文件)
“Live Binding”不支持支持。导入的变量会随着原始模块的改变而更新

详细解释:

  1. 语法差异:

    • CommonJS: 使用 module.exports 直接赋值或通过操作 exports 对象来导出。导入时使用 require(),返回的是模块导出的值。
    • ES6: 使用 export 关键字显式标记需要导出的变量、函数、类等。可以导出多个命名的成员,也可以使用 export default 导出一个默认值。导入时使用 import 关键字,可以选择性地导入需要的命名成员或导入默认导出。
  2. 导出类型:

    • CommonJS: 最终导出的总是一个单一的对象。即使你通过 exports 添加了多个属性,require() 返回的也是这个包含这些属性的对象。
    • ES6: 可以导出多个独立的、命名的绑定。这意味着导入的变量和原始模块导出的变量之间存在实时的连接。如果原始模块导出的变量发生变化,导入的变量也会随之更新 (live binding)。同时,ES6 模块还支持一个匿名或命名的默认导出。
  3. 加载时机:

    • CommonJS: 模块在运行时加载。require() 语句在代码执行到那一行时才会去加载和执行对应的模块。这意味着依赖关系是在运行时确定的。
    • ES6: 模块在编译时进行静态分析。import 语句在代码执行之前就被处理,模块的依赖关系在编译阶段就确定了。这为静态分析和优化(如 Tree Shaking)提供了基础。
  4. 静态分析和 Tree Shaking:

    • CommonJS: 由于是运行时加载,难以进行可靠的静态分析,因此不支持 Tree Shaking(移除未使用的代码)。
    • ES6: 静态分析使得编译器可以知道模块导出了哪些成员以及哪些成员被导入和使用,从而可以安全地移除未被使用的代码,减小最终的 bundle 大小。
  5. 循环依赖处理:

    • CommonJS: 在处理循环依赖时可能会比较复杂,可能会遇到只加载到部分导出的情况,或者在某些情况下导致错误。
    • ES6: ES6 模块在处理循环依赖方面更加健壮,它允许模块先执行一部分代码,然后再处理循环依赖,通常能更好地解决这类问题。
  6. 适用环境:

    • CommonJS: 是 Node.js 的原生模块系统,在 Node.js 环境中广泛使用。
    • ES6: 是 JavaScript 语言的标准模块系统,被现代浏览器广泛支持。Node.js 也从较新的版本开始支持 ES6 模块,但通常需要使用 .mjs 文件扩展名或者在 package.json 中进行配置 ("type": "module")。
  7. “Live Binding” (实时绑定):

    • CommonJS: 不支持 live binding。require() 导入的是导出值的拷贝(浅拷贝)。如果原始模块导出的值在之后发生变化,导入的变量不会自动更新。
    • ES6: 支持 live binding。import 导入的是对导出变量的引用。当原始模块中导出的变量改变时,所有导入该变量的地方都会同步更新。

总结来说:

ES6 模块系统是 JavaScript 语言层面的标准化模块方案,它在语法、静态分析、Tree Shaking 和处理循环依赖等方面都比 CommonJS 更加先进和强大。虽然 CommonJS 在 Node.js 环境中仍然被广泛使用,但随着 JavaScript 生态的发展,ES6 模块正逐渐成为主流。在现代前端开发中,ES6 模块几乎是唯一的选择。在 Node.js 项目中,也越来越倾向于使用 ES6 模块,尤其是在新的项目中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值