NodeJS / Express 中的“module.exports”和“exports.methods”是啥意思?

Posted

技术标签:

【中文标题】NodeJS / Express 中的“module.exports”和“exports.methods”是啥意思?【英文标题】:What do "module.exports" and "exports.methods" mean in NodeJS / Express?NodeJS / Express 中的“module.exports”和“exports.methods”是什么意思? 【发布时间】:2011-09-01 07:08:24 【问题描述】:

查看express 框架的express 的随机source file,有两行代码我不明白(这些代码行是几乎所有NodeJS 文件的典型代码)。

/**
 * Expose `Router` constructor.
 */

exports = module.exports = Router;

/**
 * Expose HTTP methods.
 */

var methods = exports.methods = require('./methods');

我了解第一段代码 允许将文件中的其余函数暴露给NodeJS应用程序,但我不完全了解它是如何工作的,或者该行中的代码是什么意思。

exportsmodule.exports 究竟是什么意思?

我相信第二段代码允许文件中的函数访问methods,但同样,它究竟是如何做到这一点的。

基本上,这些神奇的词是什么:moduleexports

【问题讨论】:

【参考方案1】:

更具体:

module 是文件内的全局范围变量。

所以如果你打电话给require("foo") 那么:

// foo.js
console.log(this === module); // true

它的行为方式与window 在浏览器中的行为方式相同。

还有另一个名为 global 的全局对象,你可以在任何你想要的文件中写入和读取,但这涉及到改变全局范围,这是 EVIL

exports 是一个存在于module.exports 上的变量。它基本上是您在需要文件时导出的内容。

// foo.js
module.exports = 42;

// main.js
console.log(require("foo") === 42); // true

exports 本身存在一个小问题。 _global 范围 context+ 和 module 相同。 (在浏览器中全局作用域上下文和window是一样的)。

// foo.js
var exports = ; // creates a new local variable called exports, and conflicts with

// living on module.exports
exports = ; // does the same as above
module.exports = ; // just works because its the "correct" exports

// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works

Read more about exports

【讨论】:

你可以解释为什么 exports = module.exports = Router;使用构造? 这很不幸,因为到目前为止我看到的大多数源(我承认非常有限)都使用它,包括 connect.js @ShaneCourtrille 他似乎想将module.exports 设置为Router,然后想将属性添加到exports 而不是Router,所以这就是他做这三个的原因。我认为这是一种愚蠢的编码风格,因为他可以直接将属性添加到Router 我不敢相信我已经使用 Node.JS 这么长时间了,并且一直认为全局对象是 process 而不是 module。 +1 @ShaneCourtrille 这个答案更详细地解释了原因:***.com/a/17944431/404699【参考方案2】:

module 是一个对象,表示该特定源文件想要公开公开的内容。您可以通过定义此对象来描述模块导出的内容,而不是类似于 c/c++ 世界中的头文件。然后节点运行时使用这个对象来确定你的模块是“公共的”。

它的概念类似于从编译世界中的 dll 导出函数。您必须明确定义外部世界可以访问哪些功能。这有助于封装并让您以简洁的方式组织库。

【讨论】:

【参考方案3】:

扩展 Raynos 的答案...

exports 基本上是module.exports别名 - 我建议不要使用它。您可以通过在module.exports上设置方法和属性来公开模块中的方法和属性,如下所示:

//file 'module1.js'
module.exports.foo = function ()  return 'bar' 
module.exports.baz = 5

然后你可以在你的代码中访问它:

var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)

您还可以完全覆盖 module.exports 以简单地在需要时提供单个对象:

//glorp.js
module.exports = function () 
  this.foo = function ()  return 'bar' 
  this.baz = 5
  return this // need to return `this` object here

现在你已经有了一个不错的原型:

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)

module.exportsrequire 还有许多其他玩法。请记住,require('foo') 总是返回同一个实例,即使您多次调用它。

注意

为了以下工作,

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz) 

this 必须在分配给module.exports 的函数中返回。否则,你会得到一个TypeError

console.log(g1.foo())
          ^
TypeError: Cannot read property 'foo' of undefined

【讨论】:

【参考方案4】:

您可以在 node.js 源代码中找到最佳答案。 如果有人需要你的 js 模块, 您的脚本按节点变成一个函数,如下所示(参见 src/node.js)。

// require function does this..
(function (exports, require, module, __filename, __dirname) 
    ... your javascript contents...
);

Node 将包装您的脚本。那么上面的脚本会执行如下:

//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

所以在你的脚本中,

exports is just module.exports.

在您的脚本中,您可以向该导出对象(函数..)添加一些内容。 require 函数将返回此对象。这是node.js的模块系统(commonJS规范)。

但注意不要修改module.exports。否则,您当前的导出将毫无意义。

【讨论】:

【参考方案5】:

模块的代码被包裹在module.exports(模块,可能由其他模块组成)中。 构建模块的方法有很多种,但这是一种非常常见的方法(也是我个人最喜欢的一种)。

// Dependencies
// const module = require('module');

// Module object
var foo = 

// Internal property
foo._a = 'a';

// "Public" property
foo.b = 'b';

// Method
foo.fu = function()  return 'fu' ;

// Export
module.exports = foo;

【讨论】:

以上是关于NodeJS / Express 中的“module.exports”和“exports.methods”是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

nodejs / express中的数据库会话支持[关闭]

NodeJS / Express 中的“module.exports”和“exports.methods”是啥意思?

Node.js / Express with vhost 与 Sails.js 框架应用程序冲突

javascript NodeJs + Express中的CORS问题

NodeJs中的express框架获取http参数

POST 中的 nodejs/express 和二进制数据