CommonJs模块系统中“module.exports”和“exports”的区别
在这个页面上( http://docs.nodejitsu.com/articles/getting-started/what-is-require ),它指出:“如果你想把exports对象设置为一个函数或一个新的对象,你必须使用module.exports对象“。
我的问题是为什么。
// right module.exports = function () { console.log("hello world") } // wrong exports = function () { console.log("hello world") }  我console.logged结果( result=require(example.js) ),第一个是[Function]第二个是{} 。 
你能解释一下它背后的原因吗? 我在这里阅读这篇文章: module.exports vs在Node.js中导出 。 这是有帮助的,但没有解释为什么这样devise的原因。 如果直接返回出口的参考资料,会出现问题吗?
  module是一个带有exports属性的普通JavaScript对象。  exports是一个普通的JavaScriptvariables,恰好被设置为module.exports 。 在文件的最后,node.js基本上将module.exports返回给require函数。 在Node中查看JS文件的简单方法可能是这样的: 
 var module = { exports: {} }; var exports = module.exports; // your code return module.exports; 
 如果你设置一个exports属性,比如exports.a = 9;  ,也会设置module.exports.a ,因为对象是作为JavaScript中的引用传递的,这意味着如果你为同一个对象设置多个variables,它们都是同一个对象; 那么exports和module.exports是同一个对象。 
 但是,如果将exports设置为新的内容,则不再将其设置为module.exports ,因此exports和module.exports不再是同一个对象。 
蕾妮的回答很好解释。 除了用一个例子来回答:
节点为你的文件做了很多事情,其中一个重要的事情是包装你的文件。 在nodejs内部返回源代码“module.exports”。 让我们退后一步,了解包装。 假设你有
greet.js
 var greet = function () { console.log('Hello World'); }; module.exports = greet; 
上面的代码被封装为nodejs源代码中的IIFE(即时调用函数expression式),如下所示:
 (function (exports, require, module, __filename, __dirname) { //add by node var greet = function () { console.log('Hello World'); }; module.exports = greet; }).apply(); //add by node return module.exports; //add by node 
并调用上述函数(.apply())并返回module.exports。 此时module.exports和exports指向相同的引用。
现在,想象你重写greet.js为
 exports = function () { console.log('Hello World'); }; console.log(exports); console.log(module.exports); 
输出将是
 [Function] {} 
原因是:module.exports是一个空的对象。 我们没有设置任何东西到module.exports而是我们设置exports = function()…..在新的greet.js。 所以,module.exports是空的。
技术上出口和module.exports应该指向相同的参考(即正确!!)。 但是,在将function()分配给导出时,我们使用“=”,这会在内存中创build另一个对象。 所以,module.exports和exports会产生不同的结果。 说到出口,我们不能重写它。
现在,想象你重写(这称为突变)greet.js(指Renee答案)为
 exports.a = function() { console.log("Hello"); } console.log(exports); console.log(module.exports); 
输出将是
 { a: [Function] } { a: [Function] } 
正如你所看到的module.exports和exports是指向相同的引用,这是一个函数。 如果你在导出上设置属性,那么它将被设置在module.exports上,因为在JS中,对象是通过引用传递的。
结论总是使用module.exports来避免混淆。 希望这可以帮助。 快乐编码:)
另外,有一件事可能有助于理解:
math.js
 this.add = function (a, b) { return a + b; }; 
client.js
 var math = require('./math'); console.log(math.add(2,2); // 4; 
伟大的,在这种情况下:
 console.log(this === module.exports); // true console.log(this === exports); // true console.log(module.exports === exports); // true 
因此,默认情况下,“this”实际上等于module.exports。
但是,如果您将您的实施更改为:
math.js
 var add = function (a, b) { return a + b; }; module.exports = { add: add }; 
在这种情况下,它会正常工作,但是,“this”不等于module.exports,因为创build了一个新的对象。
 console.log(this === module.exports); // false console.log(this === exports); // true console.log(module.exports === exports); // false 
而现在,require的返回值是module.exports中定义的内容,而不是this或者exports。
另一种做法是:
math.js
 module.exports.add = function (a, b) { return a + b; }; 
要么:
math.js
 exports.add = function (a, b) { return a + b; }; 
  Rene关于exports和module.exports之间的关系的回答是非常明确的,这些都是关于javascript引用的。 只是想补充一点: 
我们在许多节点模块中看到这一点:
 var app = exports = module.exports = {}; 
这将确保即使我们改变了module.exports,我们仍然可以通过使这两个variables指向同一个对象来使用导出。