朗润西的回答解释得很清楚。以下是一个带有示例的额外回答:
Node对您的文件进行了许多操作,其中一个重要的操作是包装您的文件。在nodejs源代码中,返回的是"module.exports"。让我们退后一步,了解一下包装器。假设你有
greet.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
以上代码被封装为IIFE(立即调用函数表达式)并嵌入Node.js源代码中,如下所示:
(function (exports, require, module, __filename, __dirname) {
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply();
return module.exports;
上述函数被调用(使用.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 设置任何内容,而是在新的 greet.js 中设置了 exports = function().....。所以,module.exports 是空的。
技术上讲,exports 和 module.exports 应该指向同一个引用(没错!!)。但是我们在将 function().... 赋给 exports 时使用 "=",这会在内存中创建另一个对象。因此,module.exports 和 exports 产生不同的结果。对于 exports,我们无法覆盖它。
现在,想象一下你重新编写(这被称为 Mutation)greet.js(参考 Renee 的答案),如下所示:
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
输出结果将会是:
{ a: [Function] }
{ a: [Function] }
正如您所看到的,module.exports和exports指向相同的引用,它是一个函数。如果在exports上设置属性,则会在module.exports上设置该属性,因为在JS中,对象是按引用传递的。
结论是始终使用module.exports以避免混淆。希望这可以帮助到你。愉快的编码:)
module.exports
。 - Gabriel Llamasexports
,例如 https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js? - CodyBugsteinmodule.exports
,就永远不会出错,但是如果你不替换默认导出的对象,可以使用exports
,也就是说,如果你只是像这样附加属性:var foo = require('foo').foo
。可以像这样导出foo
属性:exports.foo = ...
,当然也可以使用module.exports
。这是个人选择,但我目前适当地使用module.exports
和exports
。 - Gabriel Llamasexports.myFunc = function() {}
,这样我就不必在文件底部维护一个导出列表。它更接近于ES6中声明时导出的常见做法。 - SacWebDeveloper