module.exports vs Node.js中的导出

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

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

我想知道module.exportsexports之间有什么不同,以及为什么两者都用在这里。


设置module.exports允许database_module时要调用的函数的功能等required 。 简单地设置exports将不允许导出函数,因为节点导出对象module.exports引用。 以下代码不允许用户调用该函数。

module.js

以下将无法使用。

exports = nano = function database_module(cfg) {return;}

如果设置了module.exports ,以下将会工作。

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

安慰

var func = require('./module.js');
// the following line will **work** with module.exports
func();

基本上, node.js不会导出exports当前引用的对象,但会exports最初引用的导出属性。 尽管Node.js不会导出对象module.exports引用,但可以将其称为函数。


第二个不重要的原因

他们设置module.exportsexports以确保exports不引用先前导出的对象。 通过设置您的exports作为速记,并避免后来的潜在错误。

使用module.exports.prop = true exports.prop = true而不是module.exports.prop = true可以保存字符并避免混淆。


即使问题早已得到回答和接受,我只想分享我的2分钱:

你可以想象,在你的文件的开头有一些像(仅仅为了解释):

var module = new Module(...);
var exports = module.exports;

在这里输入图像描述

因此,无论您只是牢记module.exports和NOT exports将从您的模块返回,当您从其他地方需要该模块时。

所以当你做这样的事情时:

exports.a = function() {
    console.log("a");
}
exports.b = function() {
    console.log("b");
}

要添加2函数“a”和“B”在其上太module.exports点对象,所以typeof返回的结果将是一个object{ a: [Function], b: [Function] }

当然,如果您在本例中使用module.exports而不是exports则会得到相同的结果。

在这种情况下,您希望module.exports的行为类似于导出值的容器。 然而,如果你只想导出一个构造函数,那么你应该知道使用module.exportsexports ;(再次记住,当你需要某些东西而不是导出时,module.exports会被返回)。

module.exports = function Something() {
    console.log('bla bla');
}

现在typeof返回结果是'function' ,你可以要求它并立即调用,如:
var x = require('./file1.js')(); 因为你覆盖返回的结果是一个函数。

但是,使用exports你不能使用像这样的东西:

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

因为对于exports ,引用不再'指向' module.exports指向的对象,所以exportsmodule.exports之间不再有关系。 在这种情况下,module.exports仍然指向将返回的空对象{}

来自另一主题的接受答案也应该有所帮助:Javascript是否通过引用?


基本上,答案在于通过require语句require模块时发生的真实情况。 假设这是第一次需要该模块。

例如:

var x = require('file1.js');

file1.js的内容:

module.exports = '123';

当执行上述语句时,将创建一个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 = [];
}

正如你看到的每个模块对象都有一个名称为exports的属性。 这是最终返回作为require一部分。

require的下一步是将file1.js的内容封装到如下的匿名函数中:

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

而这个匿名函数被调用下面的方式, module这里指的是Module前面创建的对象。

(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");

正如我们在函数内部看到的, exports正式参数指的是module.exports 。 实质上,它是为模块程序员提供的便利。

然而,这种便利需要谨慎行事。 无论如何,如果试图将新对象分配给出口,确保我们这样做。

exports = module.exports = {};

如果我们按照错误的方式执行它, module.exports仍然会指向作为模块实例的一部分创建的对象。

exports = {};

因此,向上述exports对象添加任何内容都不会对module.exports对象产生任何影响,并且不会将任何内容作为require的一部分导出或返回。

链接地址: http://www.djcxy.com/p/17371.html

上一篇: module.exports vs exports in Node.js

下一篇: What is the equivalent of Java's final in C#?