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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5311334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:35:51  来源:igfitidea点击:

What is the purpose of Node.js module.exports and how do you use it?

javascriptnode.js

提问by mrwooster

What is the purpose of Node.js module.exports and how do you use it?

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

I can't seem to find any information on this, but it appears to be a rather important part of Node.js as I often see it in source code.

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

According to the Node.js documentation:

根据Node.js 文档

module

A reference to the current module. In particular module.exportsis the same as the exports object. See src/node.jsfor more information.

模块

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

But this doesn't really help.

但这并没有真正的帮助。

What exactly does module.exportsdo, and what would a simple example be?

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

回答by Alnitak

module.exportsis the object that's actually returned as the result of a requirecall.

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

The exportsvariable is initially set to that same object (i.e. it's a shorthand "alias"), so in the module code you would usually write something like this:

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

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

to export (or "expose") the internally scoped functions myFunc1and myFunc2.

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

And in the calling code you would use:

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

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

where the last line shows how the result of requireis (usually) just a plain object whose properties may be accessed.

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

NB: if you overwrite exportsthen it will no longer refer to module.exports. So if you wish to assign a new object (or a function reference) to exportsthen you should also assign that new object to module.exports

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



It's worth noting that the name added to the exportsobject does not have to be the same as the module's internally scoped name for the value that you're adding, so you could have:

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

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

followed by:

其次是:

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

回答by Jed Watson

This has already been answered but I wanted to add some clarification...

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

You can use both exportsand module.exportsto import code into your application like this:

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

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

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

The basic use case you'll see (e.g. in ExpressJS example code) is that you set properties on the exportsobject in a .js file that you then import using require()

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

So in a simple counting example, you could have:

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

(counter.js):

(计数器.js):

var count = 1;

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

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

... then in your application (web.js, or really any other .js file):

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

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

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

In simple terms, you can think of required files as functions that return a single object, and you can add properties (strings, numbers, arrays, functions, anything) to the object that's returned by setting them on exports.

简单来说,您可以将所需文件视为返回单个对象的函数,并且您可以通过将属性(字符串、数字、数组、函数、任何东西)设置为 来向返回的对象添加属性exports

Sometimes you'll want the object returned from a require()call to be a function you can call, rather than just an object with properties. In that case you need to also set module.exports, like this:

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

(sayhello.js):

(sayhello.js):

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

(app.js):

(app.js):

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

The difference between exports and module.exports is explained better in this answer here.

此处的答案中更好地解释了导出和 module.exports 之间的区别。

回答by Alexandre Morgaut

Note that the NodeJS module mechanism is based on CommonJSmodules which are supported in many other implementations like RequireJS, but also SproutCore, CouchDB, Wakanda, OrientDB, ArangoDB, RingoJS, TeaJS, SilkJS, curl.js, or even Adobe Photoshop(via PSLib). You can find the full list of known implementations here.

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

Unless your module use node specific features or module, I highly encourage you then using exportsinstead of module.exportswhich is not part of the CommonJS standard, and then mostly not supported by other implementations.

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

Another NodeJS specific feature is when you assign a reference to a new object to exportsinstead of just adding properties and methods to it like in the last example provided by Jed Watson in this thread. I would personally discourage this practice as this breaks the circular reference supportof the CommonJS modules mechanism. It is then not supported by all implementations and Jed example should then be written this way (or a similar one) to provide a more universal module:

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

(sayhello.js):

(sayhello.js):

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

(app.js):

(app.js):

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

Or using ES6 features

或者使用 ES6 特性

(sayhello.js):

(sayhello.js):

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

(app.js):

(app.js):

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

PS: It looks like Appcelerator also implements CommonJS modules, but without the circular reference support (see: Appcelerator and CommonJS modules (caching and circular references))

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

回答by Alexandre Morgaut

Some few things you must take care if you assign a reference to a new object to exportsand /or modules.exports:

如果将新对象的引用分配给exports和/或,则必须注意以下几点modules.exports

1. All properties/methods previously attached to the original exportsor module.exportsare of course lost because the exported object will now reference another new one

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

This one is obvious, but if you add an exported method at the beginning of an existing module, be sure the native exported object is not referencing another object at the end

这是显而易见的,但是如果您在现有模块的开头添加导出的方法,请确保本机导出的对象最后没有引用另一个对象

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. In case one of exportsor module.exportsreference a new value, they don't reference to the same object any more

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. Tricky consequence. If you change the reference to both exportsand module.exports, hard to say which API is exposed (it looks like module.exportswins)

3. 棘手的后果。如果更改,参照上述两个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() {}; 

回答by anish

the module.exports property or the exports object allows a module to select what should be shared with the application

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

enter image description here

在此处输入图片说明

I have a video on module_export available here

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

回答by pspi

When dividing your program code over multiple files, module.exportsis used to publish variables and functions to the consumer of a module. The require()call in your source file is replaced with corresponding module.exportsloaded from the module.

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

Remember when writing modules

编写模块时记住

  • Module loads are cached, only initial call evaluates JavaScript.
  • It's possible to use local variables and functions inside a module, not everything needs to be exported.
  • The module.exportsobject is also available as exportsshorthand. But when returning a sole function, always use module.exports.
  • 模块加载被缓存,只有初始调用评估 JavaScript。
  • 可以在模块内使用局部变量和函数,并非所有内容都需要导出。
  • module.exports对象也可用作exports速记。但是当返回一个唯一的函数时,总是使用module.exports.

module exports diagram

模块导出图

According to: "Modules Part 2 - Writing modules".

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

回答by qianjiahao

the refer link is like this:

参考链接是这样的:

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

the properties of exportsor module.exports,such as functions or variables , will be exposed outside

exports或的属性module.exports,例如函数或变量,将暴露在外部

there is something you must pay more attention : don't overrideexports .

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

why ?

为什么 ?

because exports just the reference of module.exports , you can add the properties onto the exports ,but if you override the exports , the reference link will be broken .

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

good example :

好的例子 :

exports.name = 'william';

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

bad example :

不好的例子:

exports = 'william';

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

If you just want to exposed only one function or variable , like this:

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

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

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

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

this module only exposed one function and the property of name is private for the outside .

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

回答by JumpMan

There are some default or existing modules in node.js when you download and install node.js like http, sysetc.

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

Since they are already in node.js, when we want to use these modules we basically do like import modules, but why? because they are already present in the node.js. Importing is like taking them from node.js and putting them into your program. And then using them.

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

Whereas Exportsis exactly the opposite, you are creating the module you want, let's say the module addition.js and putting that module into the node.js, you do it by exporting it.

导出正好相反,你正在创建你想要的模块,假设模块addition.js 并将该模块放入node.js,你通过导出它来完成。

Before I write anything here, remember, module.exports.additionTwois same as exports.additionTwo

之前,我在这里写东西,记住,module.exports.additionTwo是一样exports.additionTwo

Huh, so that's the reason, we do like

嗯,这就是原因,我们确实喜欢

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

Be careful with the path

小心路径

Lets say you have created an addition.js module,

假设您已经创建了一个 add.js 模块,

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

When you run this on your NODE.JS command prompt:

当您在 NODE.JS 命令提示符下运行它时:

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

This will error out saying

这会出错说

Error: Cannot find module addition.js

错误:找不到模块addition.js

This is because the node.js process is unable the addition.js since we didn't mention the path. So, we have can set the path by using NODE_PATH

这是因为 node.js 进程无法添加 add.js,因为我们没有提到路径。所以,我们可以使用 NODE_PATH 设置路径

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

Now, this should run successfully without any errors!!

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

One more thing, you can also run the addition.js file by not setting the NODE_PATH, back to your nodejs command prompt:

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

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

Since we are providing the path here by saying it's in the current directory ./this should also run successfully.

因为我们在这里提供路径,说它在当前目录中,所以它./也应该成功运行。

回答by Shantanu Madane

A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file.

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

Suppose there is a file Hello.js which include two functions

假设有一个文件 Hello.js,其中包含两个函数

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

We write a function only when utility of the code is more than one call.

我们仅在代码的效用不止一次调用时才编写函数。

Suppose we want to increase utility of the function to a different file say World.js,in this case exporting a file comes into picture which can be obtained by module.exports.

假设我们想将函数的实用性增加到一个不同的文件,比如 World.js,在这种情况下,导出一个文件可以通过 module.exports 获得。

You can just export both the function by the code given below

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

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

Now you just need to require the file name into World.js inorder to use those functions

现在你只需要将文件名添加到 World.js 中即可使用这些函数

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

回答by Moriarty

The intent is:

意图是:

Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

模块化编程是一种软件设计技术,它强调将程序的功能分成独立的、可互换的模块,这样每个模块都包含执行所需功能的一个方面所需的一切。

Wikipedia

维基百科

I imagine it becomes difficult to write a large programs without modular / reusable code. In nodejs we can create modular programs utilising module.exportsdefining what we expose and compose our program with require.

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

Try this example:

试试这个例子:

fileLog.js

文件日志.js

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

module.exports = log;

stdoutLog.js

标准输出日志.js

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

module.exports = log;

program.js

程序.js

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

log('hello world!');

execute

执行

$ node program.js

hello world!

$ 节点程序.js

你好,世界!

Now try swapping ./stdoutLog.jsfor ./fileLog.js.

现在尝试换./stdoutLog.js./fileLog.js