我在 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 的一部分导出或返回。