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


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

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

根据 Node.js文档

 

对当前的参考    module。尤其是 module.exports   与exports对象相同。看到    src/node.js 了解更多信息。

但这并没有真正帮助。

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


1238
2018-03-15 11:56


起源




答案:


module.exports 是实际返回的对象是a的结果 require 呼叫。

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

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

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

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

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

1454
2018-03-15 12:00



很好的答案 - 在我看来,'暴露'将是比'出口'更好的术语选择 - UpTheCreek
啊,我好像找到了...... commonjs.org/specs/modules/1.0 - aikeru
@ ApopheniaOverload - 您可以执行“exports.func1,exports.func2等”以从一个文件中获取多个公开的方法。 - hellatan
模块要求应该是 var m = require('./ mymodule');,用点和斜线。这样Node.js知道我们正在使用本地模块。 - Gui Premonsa
一定要使用:require('。/ module_name')语法,因为可能有一些其他node.js模块带有一些名称,而不是选择你自己的模块,它将选择与node.js一起安装的模块。 - Sazid


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

你可以使用两者 exports 和 module.exports 将代码导入您的应用程序,如下所示:

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

您将看到的基本用例(例如在ExpressJS示例代码中)是您在上面设置属性 exports 然后使用导入的.js文件中的对象 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

有时你会想要从a返回的对象 require() call是一个你可以调用的函数,而不仅仅是一个具有属性的对象。在这种情况下,您还需要设置 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之间的区别更好地解释了 这个答案在这里


194
2017-10-16 05:03



我如何调用需要一些模块从其他文件夹中没有一些根文件夹作为我的? - Igal
@ user301639您可以使用相对路径遍历文件系统层次结构。 require 相对于您执行的文件夹启动 node app.js in。我建议您使用显式代码+文件夹结构示例发布一个新问题,以获得更清晰的答案。 - Jed Watson
我不得不调整你的module.exports示例以使其工作。文件: var sayHello = require('./ex6_module.js'); console.log(sayHello()); 和模块: module.exports = exports = function() { return "Hello World!"; } - Jason Lydon
发现增量示例真的很好,我每次因为我对输出做的事情超负荷时都用它来刷新我的想法。 - munkee


请注意,NodeJS模块机制基于 CommonJS的 许多其他实现中支持的模块,如 RequireJS, 但也 SproutCore的CouchDB的WakandaOrientDBArangoDBRingoJSTeaJSSilkJScurl.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模块(缓存和循环引用)


53
2018-01-20 12:35





如果您为新对象分配引用,则必须注意一些事项 exports 和/或 modules.exports

1.以前附在原件上的所有属性/方法 exports 要么 module.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.如果是其中之一 exports 要么 module.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.棘手的后果。如果您更改两者的引用 exports 和 module.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() {}; 

31
2018-01-25 09:02





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

enter image description here

我有一个关于module_export的视频 这里


23
2017-09-03 19:01



我理解你 。谢谢 - Kumaresan Perumal


将程序代码划分为多个文件时 module.exports 用于将变量和函数发布给模块的使用者。该 require() 您的源文件中的调用将替换为相应的 module.exports 从模块加载。

编写模块时请记住

  • 模块加载被缓存,只有初始调用评估JavaScript。
  • 可以在模块中使用局部变量和函数,而不是所有需要导出的东西。
  • module.exports 对象也可用作 exports 速记。但是当返回单一功能时,请始终使用 module.exports

module exports diagram

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


17
2017-08-06 21:05





引用链接是这样的:

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

的属性 exports 要么 module.exports ,如函数或变量,将暴露在外面

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

为什么?

因为只导出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的属性对于外部是私有的。


8
2018-04-18 00:53





当您下载并安装node.js时,node.js中有一些默认或现有模块 http,sys 等等

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

出口 恰恰相反,你正在创建你想要的模块,让我们说模块addition.js并将该模块放入node.js,你可以通过导出它来实现。

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


4
2017-07-27 20:49



是出口还是出口? - Siva Sankar Rajendran
谢谢您的帮助 :) - JumpMan


模块将相关代码封装到单个代码单元中。创建模块时,可以将其解释为将所有相关功能移动到文件中。

假设有一个包含两个函数的文件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;

现在您只需要将文件名称放入World.js以便使用这些函数

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

1
2018-04-22 16:04



谢谢如果它帮助了你请接受我的答案:) - Shantanu Madane
派对朋友有点晚了:) - Ben Taliadoros
@BenTaliadoros我也认为他迟到了,我也认为他的anyVariable对象有很多错误。上面的行sayHelloInSpanish方法不应该以分号(;)和sayHelloInSpanish =函数错误结束。这个对象出了什么问题。我会编辑他的答案 - divine
编辑已禁用。在这个答案中,alphadogg还编辑了什么? - divine
只是格式化。除非它有一些疯狂的东西,我没有遇到过,而且我确定它不是,那么它根本不是有效的JS - Ben Taliadoros