在此页面(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")
}
我控制台。记录了结果(result=require(example.js)
),第一个是[Function]
,第二个是{}
。
请你解释背后的原因吗?我在这里阅读帖子:module.exports vs exports in Node.js。它很有帮助,但没有解释它以这种方式设计的原因。如果直接退回出口参考会有问题吗?
答案 0 :(得分:530)
module
是一个具有exports
属性的纯JavaScript对象。 exports
是一个普通的JavaScript变量,恰好设置为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中作为引用传递,这意味着如果您设置多个变量对于同一个对象,它们是所有相同的对象;因此,exports
和module.exports
是同一个对象
但是,如果您将exports
设置为新的,则不再将其设置为module.exports
,因此exports
和module.exports
不再是同一个对象。
答案 1 :(得分:37)
Renee的答案得到了很好的解释。除了一个例子的答案:
Node为您的文件做了很多事情,其中一个重要的是WRAPPING您的文件。内部nodejs源代码" module.exports"退回。让我们退后一步,了解包装器。假设你有
greet.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
以上代码在nodejs源代码中包装为IIFE(立即调用函数表达式),如下所示:
(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指向同一个引用。
现在,想象一下你重写
输出将是 原因是:module.exports是一个空对象。我们没有为module.exports设置任何东西,而是在新的greet.js中设置exports = function().....所以,module.exports是空的。 技术上,exports和module.exports应指向相同的引用(这是正确的!!)。但我们使用" ="将函数()....赋值给exports时,会在内存中创建另一个对象。因此,module.exports和exports会产生不同的结果。谈到出口,我们无法覆盖它。 现在,想象一下你重写(这叫做Mutation)
greet.js(指Renee回答)为 输出将是 正如您所见,module.exports和exports指向同一个引用,这是一个函数。如果在exports上设置属性,那么它将在module.exports上设置,因为在JS中,对象是通过引用传递的。 结论总是使用module.exports来避免混淆。
希望这可以帮助。快乐的编码:)exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
[Function]
{}
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
{ a: [Function] }
{ a: [Function] }
答案 2 :(得分:19)
另外,有一件事可能有助于理解:
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
因此,默认情况下,"这个"实际上等于module.exports。
但是,如果您将实施更改为:
math.js
var add = function (a, b) {
return a + b;
};
module.exports = {
add: add
};
在这种情况下,它会正常工作,然而,#34;这个"不再等于module.exports,因为创建了一个新对象。
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
现在,require将返回的内容是module.exports中定义的内容,而不是此内容或导出内容。
另一种方法是:
math.js
module.exports.add = function (a, b) {
return a + b;
};
或者:
math.js
exports.add = function (a, b) {
return a + b;
};
答案 3 :(得分:13)
Rene关于exports
和module.exports
之间关系的回答非常清楚,它都是关于javascript引用的。只想补充一点:
我们在许多节点模块中看到了这一点:
var app = exports = module.exports = {};
这将确保即使我们更改了module.exports,我们仍然可以通过使这两个变量指向同一个对象来使用导出。
答案 4 :(得分:0)
myTest.js
module.exports.get = function () {};
exports.put = function () {};
console.log(module.exports)
// output: { get: [Function], put: [Function] }
exports
和module.exports
是相同的,并且是对同一对象的引用。您可以根据需要通过两种方式添加属性。
答案 5 :(得分:0)
由于上面发布的所有答案都得到了很好的解释,我想添加一些我今天面临的问题。
当您使用导出导出某些内容时,您必须将其与变量一起使用。喜欢,
File1.js
exports.a = 5;
在另一个文件中
File2.js
const A = require("./File1.js");
console.log(A.a);
并使用module.exports
File1.js
module.exports.a = 5;
在 File2.js 中
const A = require("./File1.js");
console.log(A.a);
和默认 module.exports
File1.js
module.exports = 5;
在 File2.js 中
const A = require("./File2.js");
console.log(A);
答案 6 :(得分:0)
node 做了这样的事情:
module.exports = exports = {}
module.exports 和exports 引用同一个对象。
这样做只是为了方便。 所以不要写这样的东西
module.exports.PI = 3.14
我们可以写
exports.PI = 3.14
因此可以将属性添加到导出,但将其分配给不同的对象则不行
exports.add = function(){
.
.
}
↑ 这个没问题,和 module.exports.add = function(){...} 一样
exports = function(){
.
.
}
↑ 这不行,并且会返回空对象作为模块。exports 仍然引用 {},exports 引用不同的对象。
答案 7 :(得分:0)
module.exports
和 exports
之间有两个区别
当将单个类、变量或函数从一个模块导出到另一个模块时,我们使用 module.exports
。但是导出到多个变量或函数从一个模块到另一个模块,我们使用exports
。
module.exports
是从 require() 调用返回的对象引用。但是 exports
不是由 require() 返回的。
通过示例查看更多详细信息 >> link