协慌网

登录 贡献 社区

Node.js module.exports 的目的是什么,你如何使用它?

Node.js module.exports 的目的是什么,你如何使用它?

我似乎无法找到任何关于此的信息,但它似乎是 Node.js 的一个相当重要的部分,因为我经常在源代码中看到它。

根据Node.js 文档

对当前module引用。特别是module.exports与 exports 对象相同。有关更多信息,请参阅src/node.js

但这并没有真正帮助。

module.exports做了什么,一个简单的例子是什么?

答案

module.exports是作为require调用的结果实际返回的对象。

exports变量最初设置为同一个对象(即它是一个简写的 “别名”),所以在模块代码中你通常会写这样的东西:

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

导出(或 “公开”)内部作用域函数myFunc1myFunc2

在调用代码中,您将使用:

var m = require('./mymodule');
m.myFunc1();

最后一行显示require的结果(通常)只是一个可以访问其属性的普通对象。

注意:如果你覆盖exports那么它将不再引用module.exports 。因此,如果您希望为exports分配新对象(或函数引用),那么您还应该将该新对象分配给module.exports


值得注意的是,添加到exports对象的名称不必与您要添加的值的模块内部作用域名称相同,因此您可以:

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

其次是:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

这已经得到了回答,但我想补充一些说明......

您可以使用exportsmodule.exports将代码导入应用程序,如下所示:

var mycode = require('./path/to/mycode');

您将看到的基本用例(例如,在 ExpressJS 示例代码中)是您在. js 文件中的exports对象上设置属性,然后使用require()导入该文件

因此,在一个简单的计数示例中,您可以:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... 然后在您的应用程序(web.js,或任何其他. js 文件):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

简单来说,您可以将所需文件视为返回单个对象的函数,并且可以通过在exports上设置它们来将属性(字符串,数字,数组,函数,任何内容)添加到返回的对象。

有时您会希望从require()调用返回的对象是您可以调用的函数,而不仅仅是具有属性的对象。在这种情况下,您还需要设置module.exports ,如下所示:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

export 和 module.exports 之间的区别在这里的答案中有更好的解释。

请注意,NodeJS 模块机制基于CommonJS模块,这些模块在许多其他实现(如RequireJS)中受支持,但也包括SproutCoreCouchDBWakandaOrientDBArangoDBRingoJSTeaJSSilkJScurl.js ,甚至Adobe Photoshop (通过PSLib) )。您可以在此处找到已知实施的完整列表。

除非您的模块使用节点特定的功能或模块,否则我强烈建议您使用exports而不是module.exports ,这不是 CommonJS 标准的一部分 ,然后其他实现大多不支持。

NodeJS 的另一个特定功能是,当您将新对象的引用分配给exports而不是像在 Jed Watson 在此线程中提供的最后一个示例中那样向其添加属性和方法。我个人不鼓励这种做法,因为这打破了 CommonJS 模块机制的循环引用支持 。然后,所有实现都不支持它,Jed 示例应该以这种方式(或类似的)编写,以提供更通用的模块:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

或者使用 ES6 功能

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS:看起来 Appcelerator 还实现了 CommonJS 模块,但没有循环引用支持(参见: Appcelerator 和 CommonJS 模块(缓存和循环引用)