我在Node.js模块中找到了以下契约:
module.exports = exports = nano = function database_module(cfg) {...}
我想知道module.exports和exports之间有什么区别,为什么在这里使用它们。
我在Node.js模块中找到了以下契约:
module.exports = exports = nano = function database_module(cfg) {...}
我想知道module.exports和exports之间有什么区别,为什么在这里使用它们。
当前回答
module.exports和exports都指向同一个函数database_module(cfg){…}。1|变量a,b;2|a=b=function(){console.log(“旧”);};3|b=函数(){console.log(“New”);};4|5|a();//“旧”6|b();//“新建”您可以将第3行的b更改为a,输出是相反的。结论是:a和b是独立的。因此module.exports=exports=nano=function database_module(cfg){…}相当于:var f=函数database_module(cfg){…};模块导出=f;出口=f;假设上面是foo.js所需要的module.js。module.exports=exports=nano=function database_module(cfg){…}的好处现在很清楚了:在foo.js中,由于module.exports是必需的('./module.js'):var output=require('./modules.js')();在moduls.js中:可以使用exports代替module.exports。
因此,如果exports和module.exports都指向同一个对象,您会很高兴。
其他回答
exports和module.exports是相同的,除非在模块内重新分配导出。
考虑这一点最简单的方法是认为这一行隐式地位于每个模块的顶部。
var exports = module.exports = {};
如果在模块内重新分配导出,则在模块内将其重新分配,并且不再等于module.exports。这就是为什么,如果要导出函数,必须执行以下操作:
module.exports = function() { ... }
如果只将函数(){…}分配给导出,则将导出重新分配为不再指向module.exports。
如果您不想每次通过module.exports引用函数,可以执行以下操作:
module.exports = exports = function() { ... }
注意,module.exports是最左边的参数。
将财产附加到导出不一样,因为您不需要重新分配它。这就是为什么可以这样做的原因
exports.foo = function() { ... }
尽管这个问题早就得到了回答和接受,但我只想分享我的2分钱:
您可以想象,在文件的开头有这样的内容(仅供解释):
var module = new Module(...);
var exports = module.exports;
因此,无论您做什么,只要记住,当您从其他地方需要模块时,模块将返回module.exports和NOT导出。
所以,当你做如下事情时:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}
您正在向module.exports指向的对象添加2个函数a和b,因此返回结果的类型将是一个对象:{a:[Function],b:[Function〕}
当然,如果在本例中使用module.exports而不是exports,则会得到相同的结果。
在这种情况下,您希望module.exports的行为类似于导出值的容器。然而,如果您只想导出构造函数,那么对于使用module.exports或exports,您应该知道一些事情;(请再次记住,当您需要某些东西时,会返回module.exports,而不是export)。
module.exports = function Something() {
console.log('bla bla');
}
现在返回结果的类型是“function”,您可以要求它并立即调用,如:var x=require('./file1.js')();因为您将返回结果覆盖为函数。
但是,使用导出时不能使用以下内容:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function
因为对于导出,引用不再指向module.exports所指向的对象,因此导出和module.export之间不再存在关系。在这种情况下,module.exports仍然指向将返回的空对象{}。
另一个主题的公认答案也应有助于:JavaScript是否通过引用传递?
设置module.exports允许在需要时像调用函数一样调用database_module函数。简单地设置导出不允许函数导出,因为node导出对象模块。导出引用。以下代码不允许用户调用函数。
模块.js
以下操作不起作用。
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不导出导出当前引用的对象,而是导出导出最初引用的对象的财产。虽然Node.js确实导出了对象module.exports引用,但允许您像函数一样调用它。
第二个最不重要的原因
他们设置了module.exports和exports,以确保导出不引用先前导出的对象。通过设置这两个选项,您可以使用导出作为速记,并避免以后可能出现的错误。
使用exports.rop=true而不是module.exports.rop=true可以保存字符并避免混淆。
在节点js中,module.js文件用于运行module.load系统。每当节点执行文件时,它都会将js文件内容包装如下
'(function (exports, require, module, __filename, __dirname) {',+
//your js file content
'\n});'
由于这种包装在urjs源代码中,您可以访问导出、require、模块等。。之所以使用这种方法,是因为没有其他方法可以将js文件中的功能写入另一个文件。
然后节点使用c++执行这个包装函数。此时,传递到此函数的exports对象将被填充。
您可以在这个函数中看到参数导出和模块。实际上,exports是模块构造函数函数的公共成员。
查看以下代码
将此代码复制到b.js中
console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();
将此代码复制到.js
exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}
现在使用节点运行
这是输出
module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true
导出为[对象对象]
foo的object.keys:名称是函数(){console.log('模块导出函数')}功能到模块导出
现在删除.js中的注释行,并注释该行上方的行然后删除b.js的最后一行并运行。
在javascript世界中,不能重新分配作为参数传递的对象,但当该函数的对象设置为另一个函数的参数时,可以更改该函数的公共成员
请记住
仅当您想在使用require关键字时获取函数时,才使用module.exports。在上面的例子中,我们varfoo=require(a.js);你可以看到我们可以将foo作为函数调用;
节点文档就是这样解释的导出对象是由Module系统创建的。有时这是不可接受的,许多人希望自己的模块是某个类的实例。为此,请将所需的导出对象分配给Module.exports
JavaScript通过引用的副本传递对象
这与JavaScript中通过引用传递对象的方式有细微差别。
exports和module.exports都指向同一个对象。exports是变量,module.exports是模块对象的属性。
假设我写了这样的东西:
exports = {a:1};
module.exports = {b:12};
exports和module.exports现在指向不同的对象。修改导出不再修改module.exports。
当import函数检查module.exports时,它得到{b:12}