Javascript node.js 中的 module.exports 与导出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7137397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
module.exports vs exports in Node.js
提问by Andreas K?berle
I've found the following contract in a Node.js module:
我在 Node.js 模块中找到了以下合同:
module.exports = exports = nano = function database_module(cfg) {...}
I wonder whats the different between module.exports
and exports
and why both are used here.
我不知道什么之间的不同module.exports
和exports
为什么都被用在这里。
采纳答案by Lime
Setting module.exports
allows the database_module
function to be called like a function when required
. Simply setting exports
wouldn't allow the function to be
exported because node exports the object module.exports
references. The following code wouldn't allow the user to call the function.
设置module.exports
允许在database_module
时像函数一样调用函数required
。简单的设置exports
不允许导出函数,因为节点导出对象module.exports
引用。以下代码不允许用户调用该函数。
module.js
模块.js
The following won't work.
以下将不起作用。
exports = nano = function database_module(cfg) {return;}
The following will work if module.exports
is set.
如果module.exports
设置,以下将起作用。
module.exports = exports = nano = function database_module(cfg) {return;}
console
安慰
var func = require('./module.js');
// the following line will **work** with module.exports
func();
Basically node.jsdoesn't export the object that exports
currently references, but exports the properties of what exports
originally references. Although Node.jsdoes export the object module.exports
references, allowing you to call it like a function.
基本上node.js不会导出exports
当前引用的对象,而是导出exports
最初引用的对象的属性。尽管Node.js确实导出了对象module.exports
引用,但允许您像调用函数一样调用它。
2nd least important reason
第二个最不重要的原因
They set both module.exports
and exports
to ensure exports
isn't referencing the prior exported object. By setting both you use exports
as a shorthand and avoid potential bugs later on down the road.
他们同时设置module.exports
和exports
以确保exports
不引用先前导出的对象。通过将两者都设置exports
为速记,并避免以后出现潜在的错误。
Using exports.prop = true
instead of module.exports.prop = true
saves characters and avoids confusion.
使用exports.prop = true
而不是module.exports.prop = true
保存字符并避免混淆。
回答by Srle
Even though question has been answered and accepted long ago, i just want to share my 2 cents:
尽管很久以前就已经回答并接受了问题,但我只想分享我的 2 美分:
You can imagine that at the very beginning of your file there is something like (just for explanation):
你可以想象在你的文件的开头有这样的东西(只是为了解释):
var module = new Module(...);
var exports = module.exports;
So whatever you do just keep in mind that module.exports
and NOT exports
will be returned from your module when you're requiring that module from somewhere else.
因此,无论您做什么,请记住,当您从其他地方需要该模块时module.exports
,不会exports
从您的模块返回。
So when you do something like:
因此,当您执行以下操作时:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}
You are adding 2 function a
and b
to the object on which module.exports
points too, so the typeof
the returning result will be an object
: { a: [Function], b: [Function] }
您正在添加 2 个函数a
和b
指向的对象module.exports
,因此typeof
返回结果将是一个object
:{ a: [Function], b: [Function] }
Of course, this is the same result you will get if you are using module.exports
in this example instead of exports
.
当然,如果您module.exports
在本示例中使用exports
.
This is the case where you want your module.exports
to behave like a container of exported values. Whereas, if you only want to export a constructor function then there is something you should know about using module.exports
or exports
;(Remember again that module.exports
will be returned when you require something, not export
).
在这种情况下,您希望自己module.exports
的行为像一个导出值的容器。然而,如果您只想导出一个构造函数,那么您应该了解使用module.exports
or 的一些知识exports
;(再次记住,module.exports
当您需要某些东西时将返回,而不是export
)。
module.exports = function Something() {
console.log('bla bla');
}
Now typeof
returning result is 'function'
and you can require it and immediately invoke like:
var x = require('./file1.js')();
because you overwrite the returning result to be a function.
现在typeof
返回结果是'function'
,您可以要求它并立即调用:
var x = require('./file1.js')();
因为您将返回结果覆盖为一个函数。
However, using exports
you can't use something like:
但是,使用exports
您不能使用以下内容:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function
Because with exports
, the reference doesn't pointanymore to the object where module.exports
points, so there is not a relationship between exports
and module.exports
anymore. In this case module.exports
still points to the empty object {}
which will be returned.
因为 with exports
,引用不再指向指向的对象module.exports
,所以exports
和之间module.exports
不再有关系。在这种情况下module.exports
仍然指向{}
将返回的空对象。
Accepted answer from another topic should also help: Does Javascript pass by reference?
从另一个主题接受的答案也应该有所帮助: Does Javascript pass by reference?
回答by Chandu
Basically the answer lies in what really happens when a module is required via require
statement. Assuming this is the first time the module is being required.
基本上答案在于通过require
语句需要模块时实际发生的情况。假设这是第一次需要该模块。
For example:
例如:
var x = require('file1.js');
contents of file1.js:
file1.js 的内容:
module.exports = '123';
When the above statement is executed, a Module
object is created. Its constructor function is:
执行上述语句时,将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 = [];
}
As you see each module object has a property with name exports
. This is what is eventually returned as part of require
.
如您所见,每个模块对象都有一个 name 属性exports
。这是最终作为require
.
Next step of require is to wrap the contents of file1.js into an anonymous function like below:
require 的下一步是将 file1.js 的内容包装成一个匿名函数,如下所示:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
});
And this anonymous function is invoked the following way, module
here refers to the Module
Object created earlier.
而这个匿名函数的调用方式如下,module
这里指的Module
是之前创建的Object。
(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");
As we can see inside the function, exports
formal argument refers to module.exports
. In essence it's a convenience provided to the module programmer.
正如我们在函数内部看到的,exports
形式参数指的是module.exports
。从本质上讲,它为模块程序员提供了便利。
However this convenience need to be exercised with care. In any case if trying to assign a new object to exports ensure we do it this way.
但是,需要谨慎使用这种便利。在任何情况下,如果尝试将新对象分配给导出,请确保我们这样做。
exports = module.exports = {};
If we do it following way wrong way, module.exports
will still be pointing to the object created as part of module instance.
如果我们按照错误的方式进行操作,module.exports
仍将指向作为模块实例的一部分创建的对象。
exports = {};
As as result adding anything to the above exports object will have no effect to module.exports object and nothing will be exported or returned as part of require.
因此,向上述导出对象添加任何内容都不会对 module.exports 对象产生影响,并且不会作为 require 的一部分导出或返回任何内容。
回答by cameron
Initially,module.exports=exports
, and the require
function returns the object module.exports
refers to.
最初,module.exports=exports
和require
函数返回module.exports
所指的对象。
if we add propertyto the object, say exports.a=1
, then module.exports and exports stillrefer to the same object. So if we call require and assign the module to a variable, then the variable has a property a and its value is 1;
如果我们向对象添加属性,比如exports.a=1
,那么 module.exports 和 exports仍然指向同一个对象。因此,如果我们调用 require 并将模块分配给一个变量,那么该变量具有一个属性 a,其值为 1;
But if we overrideone of them, for example, exports=function(){}
, then they are differentnow: exports refers to a new object and module.exports refer to the original object. And if we require the file, it will not return the new object, since module.exports is not refer to the new object.
但是如果我们覆盖其中一个,例如,,exports=function(){}
那么它们现在就不同了:exports 指的是一个新对象,module.exports 指的是原始对象。如果我们需要该文件,它不会返回新对象,因为 module.exports 不是指新对象。
For me, i will keep adding new property, or override both of them to a new object. Just override one is not right. And keep in mind that module.exports
is the real boss.
对我来说,我会不断添加新属性,或者将它们都覆盖到一个新对象。只覆盖一个是不对的。请记住,这module.exports
是真正的老板。
回答by dustin.schultz
exports
and module.exports
are the same unless you reassign exports
within your module.
exports
并且module.exports
是相同的,除非你重新分配exports
你的模块中。
The easiest way to think about it, is to think that this line is implicitly at the top of every module.
考虑它的最简单方法是认为这一行隐含在每个模块的顶部。
var exports = module.exports = {};
If, within your module, you reassign exports
, then you reassign it within your module and it no longer equals module.exports
. This is why, if you want to export a function, you must do:
如果在您的模块内重新分配exports
,则您在模块内重新分配它并且它不再等于module.exports
。这就是为什么,如果你想导出一个函数,你必须这样做:
module.exports = function() { ... }
If you simply assigned your function() { ... }
to exports
, you would be reassigning exports
to no longer point to module.exports
.
如果您只是将您的function() { ... }
to分配给exports
,您将重新分配exports
to 不再指向module.exports
。
If you don't want to refer to your function by module.exports
every time, you can do:
如果你不想module.exports
每次都引用你的函数,你可以这样做:
module.exports = exports = function() { ... }
Notice that module.exports
is the left most argument.
请注意,这module.exports
是最左边的参数。
Attaching properties to exports
is not the same since you are not reassigning it. That is why this works
附加属性exports
是不一样的,因为你没有重新分配它。这就是为什么这有效
exports.foo = function() { ... }
回答by superluminary
JavaScript passes objects by copy of a reference
JavaScript 通过引用的副本传递对象
It's a subtle difference to do with the way objects are passed by reference in JavaScript.
这与 JavaScript 中对象通过引用传递的方式有细微差别。
exports
and module.exports
both point to the same object. exports
is a variable and module.exports
is an attribute of the module object.
exports
并且module.exports
都指向同一个对象。exports
是一个变量,module.exports
是模块对象的一个属性。
Say I write something like this:
说我写这样的东西:
exports = {a:1};
module.exports = {b:12};
exports
and module.exports
now point to different objects. Modifying exports no longer modifies module.exports.
exports
而module.exports
现在指向不同的对象。修改导出不再修改 module.exports。
When the import function inspects module.exports
it gets {b:12}
当导入函数检查module.exports
它时{b:12}
回答by Lyman Lai
I just make some test, it turns out that, inside nodejs's module code, it should something like this:
我只是做了一些测试,结果发现,在 nodejs 的模块代码中,它应该是这样的:
var module.exports = {};
var exports = module.exports;
so:
所以:
1:
1:
exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.
2:
2:
exports.abc = function(){}; // works!
exports.efg = function(){}; // works!
3: but, while in this case
3:但是 在这种情况下
module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)
回答by Salar
Here is a good description written about node modules in node.js in actionbook from Manningpublication.
What ultimately gets exported in your application is module.exports.
exports is set
up simply as a global reference tomodule.exports , which initially is defined as an
empty object that you can add properties to. So exports.myFuncis just shorthand
for module.exports.myFunc.
As a result, if exportsis set to anything else, it breaks thereferencebetween
module.exportsand exports . Becausemodule.exportsis what really gets
exported, exportswill no longer work as expected—it doesn't referencemodule
.exportsanymore. If you want to maintain that link, you can makemodule.exportsreferenceexports again as follows:
这是Manning出版的行动手册中关于node.js 中节点模块的一个很好的描述。
最终在您的应用程序中导出的是module.exports。出口设置仅仅作为一个全球性的参考module.exports,最初被定义为一个空的对象,您可以将属性添加。所以exports.myFunc是刚刚速记module.exports.myFunc。
因此,如果将导出设置为其他任何内容,则会破坏module.exports和exports之间
的引用。因为module.exports
是真正导出的内容,导出将不再按预期工作——它不再引用模块 .exports。如果您想保持该链接,您可以再次使module.exports引用导出,如下所示:
module.exports = exports = db;
回答by Cody
I went through some tests and I think this may shed some light on the subject...
我进行了一些测试,我认为这可能会对该主题有所了解......
app.js
:
app.js
:
var ...
, routes = require('./routes')
...;
...
console.log('@routes', routes);
...
versions of /routes/index.js
:
的版本/routes/index.js
:
exports = function fn(){}; // outputs "@routes {}"
exports.fn = function fn(){}; // outputs "@routes { fn: [Function: fn] }"
module.exports = function fn(){}; // outputs "@routes function fn(){}"
module.exports.fn = function fn(){}; // outputs "@routes { fn: [Function: fn] }"
I even added new files:
我什至添加了新文件:
./routes/index.js
:
./routes/index.js
:
module.exports = require('./not-index.js');
module.exports = require('./user.js');
./routes/not-index.js
:
./routes/not-index.js
:
exports = function fn(){};
./routes/user.js
:
./routes/user.js
:
exports = function user(){};
We get the output "@routes {}"
我们得到输出“@routes {}”
./routes/index.js
:
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
./routes/not-index.js
:
./routes/not-index.js
:
exports = function fn(){};
./routes/user.js
:
./routes/user.js
:
exports = function user(){};
We get the output "@routes { fn: {}, user: {} }"
我们得到输出“@routes { fn: {}, user: {} }”
./routes/index.js
:
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
./routes/not-index.js
:
./routes/not-index.js
:
exports.fn = function fn(){};
./routes/user.js
:
./routes/user.js
:
exports.user = function user(){};
We get the output "@routes { user: [Function: user] }"
If we change user.js
to { ThisLoadedLast: [Function: ThisLoadedLast] }
, we get the output "@routes { ThisLoadedLast: [Function: ThisLoadedLast] }".
我们得到输出“@routes { user: [Function: user] }” 如果我们user.js
改为{ ThisLoadedLast: [Function: ThisLoadedLast] }
,我们得到输出“@routes { ThisLoadedLast: [Function: ThisLoadedLast] }”。
But if we modify ./routes/index.js
...
但是如果我们修改./routes/index.js
...
./routes/index.js
:
./routes/index.js
:
module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');
./routes/not-index.js
:
./routes/not-index.js
:
exports.fn = function fn(){};
./routes/user.js
:
./routes/user.js
:
exports.ThisLoadedLast = function ThisLoadedLast(){};
... we get "@routes { fn: { fn: [Function: fn] }, ThisLoadedLast: { ThisLoadedLast: [Function: ThisLoadedLast] } }"
...我们得到“@routes { fn: { fn: [Function: fn] }, ThisLoadedLast: { ThisLoadedLast: [Function: ThisLoadedLast] } }”
So I would suggest always use module.exports
in your module definitions.
所以我建议总是module.exports
在你的模块定义中使用。
I don't completely understand what's going on internally with Node, but please comment if you can make more sense of this as I'm sure it helps.
我不完全了解 Node 内部发生了什么,但是如果您能对此有更多了解,请发表评论,因为我相信它会有所帮助。
-- Happy coding
-- 快乐编码
回答by Sudhir Srinivasan
I found this link useful to answer the above question.
我发现此链接对回答上述问题很有用。
http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/
http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/
To add to the other posts The module system in node does
添加到其他帖子节点中的模块系统确实
var exports = module.exports
before executing your code. So when you want to exports = foo , you probably want to do module.exports = exports = foo but using exports.foo = foo should be fine
在执行你的代码之前。所以当你想导出 = foo 时,你可能想做 module.exports =exports = foo 但使用exports.foo = foo 应该没问题