NodeJS / Express中的“module.exports”和“exports.methods”是什么意思?
查看NodeJS
的express
框架的随机源文件 ,有两行代码我不明白(这些代码行几乎是所有NodeJS文件的典型代码)。
/** * Expose `Router` constructor. */ exports = module.exports = Router;
和
/** * Expose HTTP methods. */ var methods = exports.methods = require('./methods');
我明白, 第一块代码 允许文件中的其余function暴露给NodeJS应用程序 ,但我不明白它是如何工作的 ,或者线上的代码是什么意思。
exports
和module.exports
究竟意味着什么?
我相信第二段代码允许文件中的函数访问methods
,但是它又是如何做到这一点的。
基本上,这些魔术词是什么: module
和exports
?
更具体:
module
是文件内的全局范围variables。
所以如果你调用require("foo")
那么:
// foo.js console.log(this === module); // true
它的行为与window
在浏览器中的作用方式相同。
还有另外一个叫做global
全局对象,你可以在你想要的任何文件中读写,但涉及到全局范围的变异,这是EVIL
exports
是一个生活在module.exports
上的variables。 这基本上是您在需要文件时导出的内容。
// foo.js module.exports = 42; // main.js console.log(require("foo") === 42); // true
自己的exports
有一个小问题。 _global作用域上下文+和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
阅读更多关于出口
为了扩大Raynos的答案
exports
基本上是module.exports
的别名 – 我build议不要使用它。 您可以通过在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
你可以在node.js源代码中find最好的答案。 如果有人需要你的js模块,你的脚本按照如下方式变成一个function节点(见src / node.js)。
// require function does this.. (function (exports, require, module, __filename, __dirname) { ... your javascript contents... });
节点将包装您的脚本。 然后上面的脚本将被执行如下:
//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。 否则,你目前的出口将是没有意义的。
模块是一个对象,它表示特定的源文件想要公开的内容。 而不是在c / c ++世界里有类似于头文件的东西,而是通过定义这个对象来描述模块导出的内容。 节点运行时然后使用这个对象来确定你的模块是“公共的”。
其类似的概念,从编译世界中的DLL导出function。 你必须明确地定义外部世界可以访问哪些function。 这有助于封装,并让您以一种干净的方式组织您的图书馆。