Nodejs exports vs module.exports
可以看下 stackoverflow 上这个回答,写的很详细:
http://stackoverflow.com/a/7142924/707911
考虑下面这个情况:
假设 a.js 的内容为:
module.exports = {a: 1};
exports.b = 2;
require 这个文件的时候只会返回 {a: 1},而不是预期的 {a: 1, b: 2}
> require('./a')
{ a: 1 }
而使用 exports = module.exports 则可以避免这个 bug 的产生:
exports = module.exports = {a: 1};
exports.b = 2;
> require(’./b’)
{ a: 1, b: 2 }
不混用的话自然不会出问题,但是很有可能因为编码时的疏忽而导致混用的出现, (尤其是当代码交给他人维护的时候。)
所以始终指定 exports = module.exports 是一个好的编程习惯。(虽然也有人反对这一做法)
回答第二个问题, exports
实际上是对 module.exports
的一个引用,当你执行
exports = {a: 1}
的时候,exports
就不再是对 module.exports
的引用了,而是指向 {a: 1}
这个对象。所以这个语句并没有改变到 module.exports
的值。
下面这个例子应当可以帮助你更好的理解:
var foo = {bar: {a: 1}}
var bar = foo.bar;
bar.b = 2;
// ok, 没有问题, foo.bar.b 也将赋值为 2,此时 foo.bar 为 {a: 1, b: 2}
bar = {c: 3};
// 这句话就有问题了,由于bar指向了一个新的对象,
// 因此 foo.bar 的值没有被改变,依然是 {a: 1, b: 2}
哈哈 都恍然大悟.
这里没有BUG. 只是要对JS 变量的引用搞清楚一下.
我也凑凑热闹,说说我的见解.
module.exports 和 exports 是引用到的同一个对象, module.exports = {}; 修改了module.exports的引用, exports 的引用且没有改变. require()的时候所引用的是module.exports 对象,自然exports 变量的引用就会会被忽略掉了咯.
所以执行下 exports = module.exports 可以预防这样的问题,阻止自己产生的BUG.
一般对于 module.exports = {a:123, b:456}
这样的情况,分开来写:
exports.a = 123;
exports.b = 456;
这样就不会有问题了,直接覆盖module.exports不是一个好习惯
同意你的观点
Amazing explanation!
exports
和 module.exports
在 Node.js 中确实指向同一个对象,但它们之间的关系和使用方式有一些细微的区别。
区别
-
初始值:
exports
是一个已经指向module.exports
的引用。module.exports
则是原始的对象。
-
修改方式:
- 直接通过
exports
添加属性时,实际上是通过module.exports
进行操作的。 - 如果直接将
exports
指向一个新的对象,则会破坏exports
与module.exports
之间的联系。
- 直接通过
示例代码
// 假设这是模块中的代码
// 方式一: 通过 exports 添加属性
exports.name = "NodeClub";
exports.version = "1.0.0";
// 方式二: 直接赋值给 exports
// 这会破坏 exports 与 module.exports 之间的联系
exports = {
name: "NodeClub",
version: "1.0.0"
};
// 方式三: 直接操作 module.exports
module.exports = {
name: "NodeClub",
version: "1.0.0"
};
实际场景
在 Node.js 中,通常推荐使用 module.exports
来定义模块导出的内容。这种方式更明确且不会出现意外情况。例如,在 routes.js
文件中,可能需要导出多个路由处理函数:
// routes.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send("Home Page");
});
router.get('/about', (req, res) => {
res.send("About Page");
});
module.exports = router;
在这个例子中,module.exports
被直接赋值为一个 express.Router()
实例,这样可以更清晰地表达意图,并且避免了潜在的问题。
总结来说,虽然 exports
和 module.exports
在某些情况下看起来是等价的,但在实际开发中,建议使用 module.exports
以保持代码的一致性和可维护性。