我在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内部的情况,但如果您能理解这一点,请发表评论,因为我相信这会有所帮助。

--快乐的编码

其他回答

“如果您希望模块导出的根是一个函数(例如构造函数),或者如果您希望在一个赋值中导出一个完整的对象,而不是一次生成一个属性,请将其分配给module.exports而不是导出。”-http://nodejs.org/api/modules.html

这显示了require()如何以最简单的形式工作,摘自Eloquent JavaScript

问题模块不可能直接导出导出对象以外的值,例如函数。例如,模块可能只希望导出其定义的对象类型的构造函数。现在,它无法做到这一点,因为require始终使用它创建的导出对象作为导出值。

解决方案为模块提供另一个变量module,它是一个具有属性导出的对象。此属性最初指向require创建的空对象,但可以用另一个值覆盖以导出其他对象。

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);

最初,module.exports=导出,require函数返回module.exports引用的对象。

如果我们向对象添加属性,比如exports.a=1,那么module.exports和exports仍然引用同一个对象。因此,如果我们调用require并将模块分配给变量,那么该变量具有属性a,其值为1;

但是如果我们重写其中一个,例如exports=function(){},那么它们现在就不同了:exports引用新对象,module.exports引用原始对象。如果我们需要该文件,它将不会返回新对象,因为module.exports不引用新对象。

对我来说,我将继续添加新属性,或者将它们都覆盖到新对象中。只是忽略一个是不正确的。请记住,module.exports才是真正的老板。

1.导出->用作单例实用程序2.模块导出->用作逻辑对象,如服务、模型等

var a = {},md={};

//首先,exports和module.exports指向同一个空Object

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

//如果将exp指向其他对象,而不是将其属性指向其他对象。md.exp将为空对象{}

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}