And*_*rle 701 javascript commonjs node.js
我在Node.js模块中找到了以下合同:
module.exports = exports = nano = function database_module(cfg) {...}
Run Code Online (Sandbox Code Playgroud)
我不知道什么之间的不同module.exports和exports为什么都被用在这里.
Srl*_*rle 473
即使问题早已得到回答和接受,我只想分享我的2美分:
您可以想象在文件的最开头有类似的东西(仅用于解释):
var module = new Module(...);
var exports = module.exports;
Run Code Online (Sandbox Code Playgroud)

所以无论你做什么,只要记住,当你从其他地方要求那个模块时module.exports,不会exports从你的模块返回.
所以当你做的事情如下:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}
Run Code Online (Sandbox Code Playgroud)
您正在向module.exports指向的对象添加2个函数'a'和'b',因此a返回的结果将是b:module.exports
当然,如果您typeof在此示例中使用而不是,则会得到相同的结果object.
在这种情况下,您希望module.exports的行为类似于导出值的容器.然而,如果你只想导出构造函数,那么你应该知道使用{ a: [Function], b: [Function] }or module.exports;(再次记住,当你需要某些东西时,会返回module.exports,而不是导出).
module.exports = function Something() {
console.log('bla bla');
}
Run Code Online (Sandbox Code Playgroud)
现在返回结果的类型是exports,您可以要求它并立即调用:
module.exports因为您将返回的结果覆盖为函数.
但是,使用module.exports你不能使用类似的东西:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function
Run Code Online (Sandbox Code Playgroud)
因为exports,该参考文献没有"点"了到物体,其中module.exports分,所以没有之间的关系export和typeof了.在这种情况下,module.exports仍然指向'function'将返回的空对象.
另一个主题的接受答案也应该有所帮助: Javascript是否通过引用传递?
Lim*_*ime 418
设置module.exports允许database_module函数像函数一样被调用required.简单设置exports将不允许导出函数,因为节点导出对象module.exports引用.以下代码不允许用户调用该函数.
以下方法无效.
exports = nano = function database_module(cfg) {return;}
Run Code Online (Sandbox Code Playgroud)
如果module.exports设置,以下将起作用.
module.exports = exports = nano = function database_module(cfg) {return;}
Run Code Online (Sandbox Code Playgroud)
安慰
var func = require('./module.js');
// the following line will **work** with module.exports
func();
Run Code Online (Sandbox Code Playgroud)
基本上,node.js不会导出exports当前引用的对象,但会导出exports最初引用的属性.虽然Node.js确实导出了对象module.exports引用,但允许您像函数一样调用它.
它们设置了两者module.exports并exports确保exports不引用先前导出的对象.通过将两者都设置exports为速记,并在以后的路上避免潜在的错误.
使用exports.prop = true 而不是module.exports.prop = true保存字符,避免混淆.
Cha*_*ndu 206
基本上答案在于通过require语句需要模块时真正发生的事情.假设这是第一次需要模块.
例如:
var x = require('file1.js');
Run Code Online (Sandbox Code Playgroud)
file1.js的内容:
module.exports = '123';
Run Code Online (Sandbox Code Playgroud)
执行上述语句时,将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 = [];
}
Run Code Online (Sandbox Code Playgroud)
如您所见,每个模块对象都有一个名称属性exports.这是最终作为一部分返回的内容require.
require的下一步是将file1.js的内容包装成一个匿名函数,如下所示:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
});
Run Code Online (Sandbox Code Playgroud)
并且以下面的方式调用此匿名函数,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");
Run Code Online (Sandbox Code Playgroud)
正如我们在函数内部所看到的,exports正式参数指的是module.exports.实质上,它为模块程序员提供了便利.
然而,这种便利需要谨慎行事.在任何情况下,如果尝试将新对象分配给导出,请确保我们这样做.
exports = module.exports = {};
Run Code Online (Sandbox Code Playgroud)
如果我们按照错误方式执行,module.exports仍将指向作为模块实例的一部分创建的对象.
exports = {};
Run Code Online (Sandbox Code Playgroud)
因此,向上述导出对象添加任何内容都不会对module.exports对象产生任何影响,并且任何内容都不会作为require的一部分导出或返回.
cam*_*ron 78
最初,module.exports=exports和require函数返回对象module.exports引用.
如果我们向对象添加属性,比如说exports.a=1,那么module.exports和exports 仍然引用同一个对象.因此,如果我们调用require并将模块分配给变量,那么变量的属性为a,其值为1;
但是,如果我们覆盖其中一个,例如,exports=function(){}那么它们现在是不同的:exports指的是一个新对象而module.exports指的是原始对象.如果我们需要该文件,它将不会返回新对象,因为module.exports不引用新对象.
对我来说,我将继续添加新属性,或将它们都覆盖到新对象.只是覆盖一个是不对的.请记住,这module.exports是真正的老板.
dus*_*ltz 52
exports并且module.exports是相同的,除非你重新分配exports你的模块中.
考虑它的最简单方法是认为这一行隐含在每个模块的顶部.
var exports = module.exports = {};
Run Code Online (Sandbox Code Playgroud)
如果在您的模块中重新分配exports,则在模块中重新分配它,它不再等于module.exports.这就是为什么,如果要导出函数,必须执行以下操作:
module.exports = function() { ... }
Run Code Online (Sandbox Code Playgroud)
如果你简单地分配你function() { ... }给exports,你会被重新分配exports到不再指向module.exports.
如果您不想module.exports每次都参考您的功能,您可以:
module.exports = exports = function() { ... }
Run Code Online (Sandbox Code Playgroud)
请注意,这module.exports是最左边的参数.
附加属性exports不一样,因为您没有重新分配它.这就是为什么这样的原因
exports.foo = function() { ... }
Run Code Online (Sandbox Code Playgroud)
sup*_*ary 26
这与在JavaScript中通过引用传递对象的方式有细微差别.
exports并且module.exports都指向同一个对象.exports是一个变量,module.exports是模块对象的一个属性.
说我写这样的东西:
exports = {a:1};
module.exports = {b:12};
Run Code Online (Sandbox Code Playgroud)
exports而module.exports现在指向不同的对象.修改导出不再修改module.exports.
当导入功能检查module.exports它得到{b:12}
小智 12
我只是进行了一些测试,结果发现,在nodejs的模块代码中,它应该是这样的:
var module.exports = {};
var exports = module.exports;
Run Code Online (Sandbox Code Playgroud)
所以:
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.
Run Code Online (Sandbox Code Playgroud)
exports.abc = function(){}; // works!
exports.efg = function(){}; // works!
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
Sal*_*lar 10
以下是关于Manning出版物行动手册中node.js中节点模块的详细描述.
最终在您的应用程序中导出的是module.exports.exports只是作为module.exports的全局引用设置,最初定义为可以添加属性的空对象.所以exports.myFunc是刚刚速记module.exports.myFunc.
因此,如果将exports设置为其他任何内容,则会破坏module.exports和exports之间
的引用.因为module.exports是真正导出的,导出将不再按预期工作 - 它不再引用模块.exports.如果要维护该链接,可以再次使module.exports
引用导出,如下所示:
module.exports = exports = db;
Run Code Online (Sandbox Code Playgroud)
我经历了一些测试,我认为这可能会对这个问题有所了解......
app.js:
var ...
, routes = require('./routes')
...;
...
console.log('@routes', routes);
...
Run Code Online (Sandbox Code Playgroud)
版本/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] }"
Run Code Online (Sandbox Code Playgroud)
我甚至添加了新文件:
./routes/index.js:
module.exports = require('./not-index.js');
module.exports = require('./user.js');
Run Code Online (Sandbox Code Playgroud)
./routes/not-index.js:
exports = function fn(){};
Run Code Online (Sandbox Code Playgroud)
./routes/user.js:
exports = function user(){};
Run Code Online (Sandbox Code Playgroud)
我们得到输出"@routes {}"
./routes/index.js:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
Run Code Online (Sandbox Code Playgroud)
./routes/not-index.js:
exports = function fn(){};
Run Code Online (Sandbox Code Playgroud)
./routes/user.js:
exports = function user(){};
Run Code Online (Sandbox Code Playgroud)
我们得到输出"@routes {fn:{},user:{}}"
./routes/index.js:
module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');
Run Code Online (Sandbox Code Playgroud)
./routes/not-index.js:
exports.fn = function fn(){};
Run Code Online (Sandbox Code Playgroud)
./routes/user.js:
exports.user = function user(){};
Run Code Online (Sandbox Code Playgroud)
我们得到输出"@routes {user:[Function:user]}"如果我们user.js改为{ ThisLoadedLast: [Function: ThisLoadedLast] },我们得到输出"@routes {ThisLoadedLast:[Function:ThisLoadedLast]}".
但是如果我们修改./routes/index.js......
./routes/index.js:
module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');
Run Code Online (Sandbox Code Playgroud)
./routes/not-index.js:
exports.fn = function fn(){};
Run Code Online (Sandbox Code Playgroud)
./routes/user.js:
exports.ThisLoadedLast = function ThisLoadedLast(){};
Run Code Online (Sandbox Code Playgroud)
...我们得到"@routes {fn:{fn:[Function:fn]},ThisLoadedLast:{ThisLoadedLast:[Function:ThisLoadedLast]}}"
所以我建议总是module.exports在你的模块定义中使用.
我不完全理解Node内部发生了什么,但如果你能更好地理解这一点,请发表评论,因为我确信它有所帮助.
- 快乐的编码
要了解差异,您必须首先了解 Node.js 在运行时对每个模块做了什么。Node.js 为每个模块创建一个包装函数:
(function(exports, require, module, __filename, __dirname) {
})()
Run Code Online (Sandbox Code Playgroud)
请注意,第一个参数exports是一个空对象,第三个参数module是一个具有许多属性的对象,其中一个属性名为exports。这就是exports从何而来,又是module.exports从何而来。前者是变量对象,后者是module对象的属性。
在模块内部,Node.js 会在开始时自动做这件事:module.exports = exports,最终返回module.exports。
因此,您可以看到,如果您将某个值重新分配给exports,则不会对 产生任何影响module.exports。(仅仅是因为exports指向另一个新对象,但module.exports仍然持有旧对象exports)
let exports = {};
const module = {};
module.exports = exports;
exports = { a: 1 }
console.log(module.exports) // {}
Run Code Online (Sandbox Code Playgroud)
但是如果你更新了 的属性exports,肯定会对module.exports. 因为它们都指向同一个对象。
let exports = {};
const module = {};
module.exports = exports;
exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }
Run Code Online (Sandbox Code Playgroud)
另请注意,如果您将另一个值重新分配给module.exports,则exports更新似乎毫无意义。每次更新都会exports被忽略,因为它module.exports指向另一个对象。
let exports = {};
const module = {};
module.exports = exports;
exports.a = 1;
module.exports = {
hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
231630 次 |
| 最近记录: |