我在Node.js模块中找到了以下契约:

module.exports = exports = nano = function database_module(cfg) {...}

我想知道module.exports和exports之间有什么区别,为什么在这里使用它们。


当前回答

我通过了一些测试,我认为这可能会对这个问题有所启发。。。

应用.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

/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] }"

我甚至添加了新文件:

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

我们得到输出“@routes{}”


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

我们得到输出“@routes{fn:{},user:{}}”


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

我们得到输出“@routes{user:[Function:user]}”如果我们将user.js更改为{ThisLoadedLast:[Function:ThisLoadedLast]},我们将得到输出“@routes{ThisLoadedLast:[Function:TThisLoadedlast]}”。


但如果我们修改/routes/index.js。。。

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

…我们得到“@routes{fn:{fn:[Function:fn]},ThisLoadedLast:{ThisLoadedLast:[Function:ThisLoadedLast]}}”

所以我建议在模块定义中始终使用module.exports。

我不完全理解Node内部的情况,但如果您能理解这一点,请发表评论,因为我相信这会有所帮助。

--快乐的编码

其他回答

我只是做了一些测试,结果发现,在nodejs的模块代码中,应该是这样的:

var module.exports = {};
var exports = module.exports;

so:

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:

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

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)

我通过了一些测试,我认为这可能会对这个问题有所启发。。。

应用.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

/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] }"

我甚至添加了新文件:

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

我们得到输出“@routes{}”


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

我们得到输出“@routes{fn:{},user:{}}”


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

我们得到输出“@routes{user:[Function:user]}”如果我们将user.js更改为{ThisLoadedLast:[Function:ThisLoadedLast]},我们将得到输出“@routes{ThisLoadedLast:[Function:TThisLoadedlast]}”。


但如果我们修改/routes/index.js。。。

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

…我们得到“@routes{fn:{fn:[Function:fn]},ThisLoadedLast:{ThisLoadedLast:[Function:ThisLoadedLast]}}”

所以我建议在模块定义中始终使用module.exports。

我不完全理解Node内部的情况,但如果您能理解这一点,请发表评论,因为我相信这会有所帮助。

--快乐的编码

要了解这些差异,您必须首先了解Node.js在运行时对每个模块做了什么。Node.js为每个模块创建一个包装函数:

 (function(exports, require, module, __filename, __dirname) {

 })()

注意,第一个param导出是一个空对象,第三个param模块是一个具有许多财产的对象,其中一个财产名为exports。这是导出的来源和module.exports的来源。前者是变量对象,后者是模块对象的属性。

在模块中,Node.js在开始时自动执行以下操作:module.exports=exports,并最终返回module.exports。

因此,您可以看到,如果您为导出重新分配一些值,那么它不会对module.exports产生任何影响

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.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 }

还要注意,如果您将另一个值重新分配给module.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')}

exports:它是对module.exports对象的引用exports和module.exports都指向同一个对象直到我们更改导出对象的引用

例子:

如果exports.a=10,则module.exports.a=10如果我们在代码中显式地重新分配exports对象exports={}现在失去了对module.exports的引用

我发现这个链接对回答上述问题很有用。

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

添加到其他帖子节点中的模块系统

var exports = module.exports 

在执行代码之前。因此,当您想要exports=foo时,您可能需要执行module.exports=exports=foo,但使用exports.foo=foo应该可以