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应用程序,但我不完全了解它是如何工作的,或者该行中的代码是什么意思。
exports
和module.exports
究竟是什么意思?
我相信第二段代码允许文件中的函数访问methods
,但同样,它究竟是如何做到这一点的。
基本上,这些神奇的词是什么:module
和exports
?
【问题讨论】:
【参考方案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.exports
和 require
还有许多其他玩法。请记住,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 中的“module.exports”和“exports.methods”是啥意思?
Node.js / Express with vhost 与 Sails.js 框架应用程序冲突