我在 Node.js 模块中找到了以下合同:
module.exports = exports = nano = function database_module(cfg) {...}我不知道什么之间的不同module.exports和exports ,为什么都被用在这里。
即使很久以前就已经回答并接受了这个问题,但我只想分享我的 2 美分:
您可以想象,在文件的开头有类似的内容(仅供说明):
var module = new Module(...);
var exports = module.exports;
所以,不管你做什么只是记住, module.exports和 NOT exports将从您的模块,当你需要从别的地方该模块被退回。
因此,当您执行以下操作时:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}要添加 2 个功能a和b与对象到module.exports点,所以typeof返回的结果将是一个object : { a: [Function], b: [Function] }
当然,这是同样的结果,如果你使用的是你会得到module.exports在这个例子中,而不是exports 。
在这种情况下,您希望您的module.exports表现得像一个导出值的容器。而如果只想导出构造函数,那么使用module.exports或exports应该有一些知识;(再次记住,在需要某些东西而不是export module.exports )。
module.exports = function Something() {
console.log('bla bla');
}现在typeof返回的结果是'function' ,您可以要求它并立即调用,例如:
var x = require('./file1.js')();因为您将返回结果覆盖为一个函数。
但是,使用exports您将无法使用以下命令:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function因为与exports ,该参考文献没有了,其中指向对象module.exports点,所以没有之间的关系exports和module.exports了。在这种情况下, module.exports仍指向将返回的空对象{}
另一个主题的公认答案也应该有所帮助: JavaScript 是否通过引用传递?
设置module.exports允许required时像调用函数一样调用database_module函数。简单地设置exports将不允许导出该函数,因为节点将导出对象module.exports引用。以下代码不允许用户调用该函数。
以下内容无效。
exports = nano = function database_module(cfg) {return;}如果设置了module.exports则以下内容将起作用。
module.exports = exports = nano = function database_module(cfg) {return;}安慰
var func = require('./module.js');
// the following line will **work** with module.exports
func();Node.js 的基本上不出口的对象, exports目前的参考,但出口的是什么性质exports最初引用。尽管Node.js确实导出了对象module.exports引用,但允许您像调用函数一样调用它。
他们同时设置module.exports和exports ,确保exports未引用之前导出的对象。通过同时设置两者,可以将exports用作速记,并避免以后出现潜在的错误。
使用exports.prop = true而不是module.exports.prop = true可以节省字符并避免混淆。
require语句需要模块时实际发生的情况。假设这是第一次需要该模块。
例如:
var x = require('file1.js');file1.js 的内容:
module.exports = '123';执行以上语句后,将Module对象。其构造函数为:
function Module(id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
if (parent && parent.children) {
parent.children.push(this);
}
this.filename = null;
this.loaded = false;
this.children = [];
}如您所见,每个模块对象都有一个名称为exports的属性。这最终是作为require一部分返回的。
require 的下一步是将 file1.js 的内容包装到一个匿名函数中,如下所示:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
});而这个匿名函数被调用下面的方式, module这里指的是Module对象之前创建。
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");正如我们在函数内部看到的那样, exports形式参数是指module.exports 。从本质上讲,这是为模块程序员提供的便利。
但是,这种便利性需要谨慎对待。无论如何,如果尝试为导出分配新对象,请确保我们采用这种方式。
exports = module.exports = {};如果我们以错误的方式进行操作, module.exports仍将指向作为模块实例一部分创建的对象。
exports = {};结果,向上述导出对象添加任何内容都不会对 module.exports 对象产生任何影响,并且任何内容都不会作为 require 的一部分导出或返回。