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

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

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

根据Node.js文档 :

对当前module引用。 特别是module.exports和exports对象是一样的。 有关更多信息,请参阅src/node.js

但是这并没有真正的帮助。

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

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

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

 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示例代码中)是,您可以使用require()导入.js文件中的exports对象的属性。

所以在一个简单的计数例子中,你可以有:

(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 

简而言之,您可以将所需的文件视为返回单个对象的函数,您可以将属性(string,数字,数组,函数,任何内容)添加到通过设置exports返回的对象中。

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

(sayhello.js):

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

(app.js):

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

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

请注意,NodeJS模块机制基于CommonJS模块,这些模块在RequireJSSproutCoreCouchDBWakandaOrientDBArangoDBRingoJSTeaJSSilkJScurl.js甚至Adobe Photoshop (通过PSLib )。 您可以在这里find已知实现的完整列表。

除非你的模块使用节点特定的function或模块,否则我强烈build议你使用module.exports 而不是使用module.exports ,它不是CommonJS标准的一部分 ,然后大部分不被其他实现支持。

另一个NodeJS特有的function是当你分配一个引用到一个新的对象来exports而不是像在Jed Watson在这个线程中提供的最后一个例子那样只是添加属性和方法。 我个人不鼓励这种做法,因为这打破了CommonJS模块机制的循环引用支持 。 那么所有的实现都不支持Jed例子,然后用这种方式(或类似的方法)来编写Jed例子来提供一个更通用的模块:

(sayhello.js):

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

(app.js):

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

或者使用ES6function

(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模块(caching和循环引用) )

如果将一个新对象的引用分配给exports和/或modules.exports则必须注意几件事情:

1.以前连接到原始exportsmodule.exports所有属性/方法当然会丢失,因为导出的对象现在将引用另一个新的

这一点很明显,但是如果您在现有模块的开头添加一个导出的方法,请确保本地导出的对象不在最后引用另一个对象

 exports.method1 = function () {}; // exposed to the original exported object exports.method2 = function () {}; // exposed to the original exported object module.exports.method3 = function () {}; // exposed with method1 & method2 var otherAPI = { // some properties and/or methods } exports = otherAPI; // replace the original API (works also with module.exports) 

2.如果exportsmodule.exports中的一个引用新值,则不会再引用同一个对象

 exports = function AConstructor() {}; // override the original exported object exports.method2 = function () {}; // exposed to the new exported object // method added to the original exports object which not exposed any more module.exports.method3 = function () {}; 

3.棘手的后果。 如果你改变了对module.exportsmodule.exports的引用,很难说哪个API被暴露(看起来像module.exports获胜)

 // override the original exported object module.exports = function AConstructor() {}; // try to override the original exported object // but module.exports will be exposed instead exports = function AnotherConstructor() {}; 

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

在这里输入图像描述

我在这里有一个关于module_export的video

将程序代码分割为多个文件时,使用module.exports将variables和函数发布到模块的使用者。 源文件中的require()调用被从模块加载的相应的module.exportsreplace。

记得在编写模块时

  • 模块加载caching,只有初始调用评估JavaScript。
  • 可以在模块中使用本地variables和函数,而不是所有的东西都需要导出。
  • module.exports对象也可用作exports速记。 但是当返回唯一的函数时,总是使用module.exports

模块导出图

根据: “模块第2部分 – 编写模块” 。

参考链接是这样的:

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

exportsmodule.exports的属性,如函数或variables,将暴露在外面

有一点你必须多加注意:不要override出口。

为什么?

因为导出只是module.exports的引用,所以可以将属性添加到导出,但是如果覆盖导出,则引用链接将被打破。

很好的例子:

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

不好的例子:

 exports = 'william'; exports = function(){ //... } 

如果你只想暴露一个函数或variables,像这样:

 // test.js var name = 'william'; module.exports = function(){ console.log(name); } // index.js var test = require('./test'); test(); 

这个模块只暴露了一个function,名称的属性是私人的。

在下载和安装node.js(如http,sys等)时,node.js中有一些默认或现有模块。

既然他们已经在node.js中,当我们想要使用这些模块时,我们基本上就像导入模块一样 ,但为什么呢? 因为它们已经存在于node.js中 导入就像从node.js中取出它们并把它们放到你的程序中。 然后使用它们。

出口正好相反,你正在创build你想要的模块,让我们说模块addition.js和把模块放入node.js,你通过导出它。

在我写任何东西之前,请记住, module.exports.additionTwo和exports.additionTwo是一样的

呵呵,所以这就是我们喜欢的原因

 exports.additionTwo = function(x) {return x+2;}; 

小心path

比方说,你已经创build了一个addition.js模块,

 exports.additionTwo = function(x){ return x + 2; }; 

当你在NODE.JS命令提示符下运行这个命令时:

 node var run = require('addition.js'); 

这将错误地说

错误:无法find模块addition.js

这是因为我们没有提到path,所以node.js进程无法执行addition.js。 所以,我们可以使用NODE_PATH来设置path

 set NODE_PATH = path/to/your/additon.js 

现在,这应该成功运行没有任何错误!

还有一件事,您也可以通过不设置NODE_PATH来运行addition.js文件,返回到您的nodejs命令提示符:

 node var run = require('./addition.js'); 

由于我们通过在当前目录中提供path来提供这个path./也应该成功运行。

一个模块将相关代码封装到一个单一的代码单元中。 当创build一个模块时,这可以解释为将所有相关的函数移动到一个文件中。

假设有一个包含两个函数的文件Hello.js

 sayHelloInEnglish = function() { return "Hello"; }; sayHelloInSpanish = function() { return "Hola"; }; 

我们只在代码的工具不止一个调用时才写一个函数。

假设我们要将函数的实用程序增加到不同的文件中,比如说World.js,在这种情况下,导出一个文件进入到可以通过module.exports获取的图片。

您可以通过下面给出的代码来导出这两个函数

 var anyVariable={ sayHelloInEnglish = function() { return "Hello"; }; sayHelloInSpanish = function() { return "Hola"; }; } module.export=anyVariable; 

现在,您只需要将文件名称inputWorld.js即可使用这些函数

 var world= require("./hello.js");