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

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

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


当前回答

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); //{}

其他回答

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() { ... }

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

module.export和exports都指向同一个对象,然后对模块求值。

使用require语句在另一个模块中使用模块时,添加到module.exports对象的任何属性都将可用。导出是一种快捷方式,可用于相同的事情。例如:

module.exports.add = (a, b) => a+b

相当于写:

exports.add = (a, b) => a+b

因此,只要不为导出变量分配新值,就可以了。当你这样做时:

exports = (a, b) => a+b 

当您为导出分配新值时,它不再引用导出的对象,因此将保持模块的本地状态。

如果您计划为module.exports分配一个新值,而不是向可用的初始对象添加新的财产,您可能应该考虑如下所示:

module.exports = exports = (a, b) => a+b

Node.js网站对此有很好的解释。

让我们用两种方式创建一个模块:

单向

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

第二种方式

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

这就是require()集成模块的方式。

第一种方式:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

第二种方式

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}

这显示了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);