exports vs module.exports
发布于 13 年前 作者 lainuo 9684 次浏览 最后一次编辑是 8 年前

大家好, 我在看nodeclub的代码, 看到这行代码产生了一点疑问:

根据文档

In particular module.exports is the same as the exports object.

exports 和 module.exports 是同一个东西, 那为什么这行代码要这样写, 有什么特别的作用呢?

11 回复

可以看下 stackoverflow 上这个回答,写的很详细:
http://stackoverflow.com/a/7142924/707911

@xqunix

这个我也搜索到了, 我不大认同这个回答

对于1st reason, module.exports = function() {}; 就可以了, 并没有解释为什么要 exports = module.exports

对于2nd reason, 在这个routes中似乎并没有用到? 还有我不大明白他所说的"potentially bugs"是指的哪种情况.

考虑下面这个情况:

假设 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 }

@xqunix

感觉这也不能算是"bug", 如果不混用的话就不会出现这个问题. 比如总是使用module.exports

我还有问题, 请赐教…既然:

console.log(exports === module.exports); // true

那么为什么exports和module.exports会有1st reason那样的区别呢?

不混用的话自然不会出问题,但是很有可能因为编码时的疏忽而导致混用的出现, (尤其是当代码交给他人维护的时候。)

所以始终指定 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}

@xqunix

感谢回答, 大概明白了, 但对于

始终指定 exports = module.exports 是一个好的编程习惯

不大同意.

考虑下面的例子:

console.log(this === module.exports);   // true
console.log(this === exports);  // true
console.log(this.exports === module.exports.exports);  // true
console.log(exports === module.exports);  // true
console.log(exports);  // {}

exports = {a: 1};
console.log(this === module.exports);   // true
console.log(this === exports);  // false
console.log(this.exports === module.exports.exports);  // true
console.log(exports === module.exports);  // false
console.log(exports);  // {a : 1}

exports = module.exports = {a: 1};
console.log(this === module.exports);   // false
console.log(this === exports);  // false
console.log(this.exports === module.exports.exports);  // true
console.log(exports === module.exports);  // true
console.log(exports);  // {a : 1}

exports = module.exports = {a: 1}; 也改变了结构, 或者说覆盖冲突一些module上的变量

哈哈 都恍然大悟.

这里没有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不是一个好习惯

同意你的观点

恩, 我也同意 @leizongmin 的观点.

回到顶部