Node.js module.exports的用途是什么?您如何使用它?

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

根据Node.js文档:

单元参考电流单元特别是module.exports与导出对象相同。看见src/node.js获取更多信息。

但这并没有真正的帮助。

module.exports到底做什么?一个简单的例子是什么?


当前回答

这已经得到了回答,但我想补充一些澄清。。。

您可以使用exports和module.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

简单地说,您可以将所需文件视为返回单个对象的函数,并且可以通过在导出时设置它们,将财产(字符串、数字、数组、函数等)添加到返回的对象中。

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

(sayhello.js):

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

(app.js):

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

这里的答案更好地解释了exports和module.exports之间的区别。

其他回答

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

exports变量最初被设置为同一个对象(即,它是一个简写“别名”),因此在模块代码中,您通常会编写如下内容:

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

导出(或“公开”)内部作用域函数myFunc1和myFunc2。

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

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

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

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


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

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

然后:

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

参考链接如下:

exports = module.exports = function(){
    //....
}

导出或模块的财产。导出,例如函数或变量,将在外部公开

有一点你必须更加注意:不要覆盖导出。

为什么?

因为导出只是module.exports的引用,所以可以将财产添加到导出中,但如果覆盖导出,引用链接将断开。

很好的例子:

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

坏例子:

exports = 'william';

exports = function(){
     //...
}

如果您只想公开一个函数或变量,如下所示:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

这个模块只公开了一个函数,name的属性对外是私有的。

ECMAScript模块-2022

从Node 14.0开始,ECMAScript模块不再是实验性的,您可以使用它们代替经典Node的CommonJS模块。

ECMAScript模块是打包JavaScript代码以供重用的官方标准格式。模块是使用各种导入和导出语句定义的。

您可以定义导出函数的ES模块:

// my-fun.mjs
function myFun(num) {
  // do something
}

export { myFun };

然后,您可以从my-fun.mjs导入导出的函数:

// app.mjs
import { myFun } from './my-fun.mjs';

myFun();

.mjs是Node.js ECMAScript模块的默认扩展名。但是,在使用package.json“type”字段或CLI中的--input-type标志解析模块时,可以将默认模块扩展配置为查找。

Node.js的最新版本完全支持ECMAScript和CommonJS模块。此外,它还提供了它们之间的互操作性。

模块导出

ECMAScript和CommonJS模块有很多不同之处,但与此问题最相关的区别是,不再需要,不再导出,不再模块。导出

在大多数情况下,ES模块导入可用于加载CommonJS模块。如果需要,可以使用module.createRequire()在ES模块中构造require函数。

ECMAScript模块发布历史记录

Release Changes
v15.3.0, v14.17.0, v12.22.0 Stabilized modules implementation
v14.13.0, v12.20.0 Support for detection of CommonJS named exports
v14.0.0, v13.14.0, v12.20.0 Remove experimental modules warning
v13.2.0, v12.17.0 Loading ECMAScript modules no longer requires a command-line flag
v12.0.0 Add support for ES modules using .js file extension via package.json "type" field
v8.5.0 Added initial ES modules implementation

您可以在Node.js存储库中找到所有变更日志

module.exports属性或exports对象允许模块选择应该与应用程序共享的内容

我这里有关于module_export的视频

目的是:

模块化编程是一种强调将程序的功能分离成独立的,可互换的模块,每个模块都包含所有必要的内容以仅执行期望功能的一个方面。

维基百科

我想,如果没有模块化/可重用代码,编写大型程序会变得困难。在nodejs中,我们可以使用module.exports创建模块化程序,该模块定义了我们公开的内容,并使用require编写程序。

请尝试以下示例:

文件日志.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

标准输出日志.js

function log(string) { console.log(string); }

module.exports = log;

程序.js

const log = require('./stdoutLog.js')

log('hello world!');

处决

$node程序.js你好,世界!

现在尝试交换/的stdoutLog.js/fileLog.js。