module.exports 是模块唯一真正的出口,exports 仅是其初始引用;修改 exports 属性有效,但重新赋值 exports 会断开与 module.exports 的关联,导致导出失败。

在 Node.js 的 CommonJS 模块系统中,module.exports 和 exports 都用于导出模块内容,但它们不是等价的——exports 只是 module.exports 的一个引用别名,且这个引用非常脆弱。真正决定模块对外暴露什么的,只有 module.exports。
exports 本质是 module.exports 的快捷引用
Node.js 在每个模块顶部默认执行了类似这样的赋值:
const exports = module.exports;也就是说,初始时 exports 和 module.exports 指向同一个空对象。此时用 exports.xxx = ... 或 exports = {...} 看似一样,实则效果完全不同:
-
exports.foo = 'bar'→ 修改的是共享对象上的属性,module.exports同步可见 -
exports = { foo: 'bar' }→ 让exports指向新对象,但module.exports仍指向原对象,**外部 require 得到的仍是旧对象(通常是空 {})**
module.exports 才是模块真正的“出口”
无论你对 exports 做了什么操作,require 时加载到的永远是 module.exports 的当前值。所以:
立即学习“Java免费学习笔记(深入)”;
- 想导出一个函数、类或任意值(不只是对象),必须直接赋值给
module.exports - 常见写法:
module.exports = function() {...}、module.exports = class A{}、module.exports = 'string' - 混用时注意:先用
exports.a = 1,再写module.exports = () =>{},后者会完全覆盖前者
什么时候可以用 exports?什么时候必须用 module.exports?
安全使用 exports 的前提:只做属性添加,不重新赋值。
- ✅ 推荐:
exports.add = (a,b) => a+b;、exports.PI = 3.14; - ❌ 危险:
exports = { add: ..., PI: ... };(丢失导出) - ✅ 必须用
module.exports:module.exports = new Date();、module.exports = require('fs');、module.exports = class DB{...};
ES Module 对比(补充说明)
注意:这是 CommonJS(Node.js 默认)的规则。ES Module(import/export)是另一套机制,export 和 export default 与 exports 完全无关,不能混用。在 Node.js 中启用 ES Module 需设置 "type": "module" 或使用 .mjs 后缀。


















