Javascript “你做什么?”;“出口”模块;及;出口.方法“;在NodeJS/Express中是什么意思?
查看Javascript “你做什么?”;“出口”模块;及;出口.方法“;在NodeJS/Express中是什么意思?,javascript,node.js,express,module,export,Javascript,Node.js,Express,Module,Export,查看express框架中的NodeJS,有两行代码我不理解(这些代码行几乎是所有NodeJS文件的典型代码) 及 我知道第一段代码允许文件中的其余函数向NodeJS应用程序公开,但我不清楚它是如何工作的,或者这行代码的意思 exports和module.exports实际上是什么意思 我相信第二段代码允许文件中的函数访问方法,但它究竟是如何做到这一点的 基本上,这些神奇的词语是什么:模块和导出?更具体地说: 模块是文件中的全局范围变量 因此,如果您调用require(“foo”),那么: //
express
框架中的NodeJS
,有两行代码我不理解(这些代码行几乎是所有NodeJS文件的典型代码)
及
我知道第一段代码允许文件中的其余函数向NodeJS应用程序公开,但我不清楚它是如何工作的,或者这行代码的意思
exports
和module.exports
实际上是什么意思
我相信第二段代码允许文件中的函数访问方法
,但它究竟是如何做到这一点的
基本上,这些神奇的词语是什么:模块
和导出
?更具体地说:
模块
是文件中的全局范围变量
因此,如果您调用require(“foo”)
,那么:
// foo.js
console.log(this === module); // true
它的作用方式与窗口
在浏览器中的作用方式相同
还有另一个名为global
的全局对象,您可以在任何需要的文件中写入和读取该对象,但这涉及到全局范围的变化,这就是EVIL
exports
是存在于模块上的变量。exports
。它基本上就是在需要文件时导出的内容
// foo.js
module.exports = 42;
// main.js
console.log(require("foo") === 42); // true
导出本身存在一个小问题。_global scope context+和模块
不相同。(在浏览器中,全局范围上下文和窗口
是相同的)
模块是一个对象,表示特定源文件想要公开的内容。在c/c++世界中没有类似于头文件的东西,而是通过定义此对象来描述模块导出的内容。然后,节点运行时使用此对象确定模块的哪些内容是“公共的”
这与在编译世界中从dll导出函数的概念类似。您必须明确定义外部世界可以访问哪些函数。这有助于封装,并让您以一种干净的方式组织库。要扩展Raynos的答案
exports
基本上是模块的别名。exports
-我建议不要使用它。通过在模块上设置方法和属性,您可以公开模块中的方法和属性。导出如下所示:
//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5
//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
然后您可以在代码中访问它:
var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)
您还可以覆盖
模块。完全导出
以根据需要提供单个对象:
//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)
使用模块还有很多其他方法。导出
和需要
。请记住,require('foo')
始终返回相同的实例,即使您多次调用它
注
为了让以下各项发挥作用
var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)
此
必须在分配给模块的函数中返回。导出
。否则,您将得到一个TypeError
:
console.log(g1.foo())
^
TypeError: Cannot read property 'foo' of undefined
您可以在node.js源代码中找到最佳答案。 如果有人需要你的js模块, 您的脚本按节点转换为函数,如下所示(请参见src/node.js) 节点将包装您的脚本。然后将按如下方式执行上述脚本:
//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5
//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。否则,您当前的导出将毫无意义。模块的代码包装在模块中。导出(该模块可能由其他模块组成)。 构建模块的方法有很多,但这是一种非常常见的方法(也是我个人的最爱)
您可以解释为什么导出=模块。导出=路由器;是否使用了构造?这很不幸,因为到目前为止我看到的大多数源代码(我承认这是非常有限的)使用它,包括连接。js@ShaneCourtrille他似乎想设置
模块。将
导出到路由器
,然后想将属性添加到导出
,而不是路由器
,这就是他为什么要执行这三项操作的原因。我认为这是一种愚蠢的编码方式,因为他可以直接将属性添加到Router
。我不敢相信我已经使用Node.JS这么长时间了,并且一直认为全局对象是process
而不是module
+1@ShaneCourtrille这个答案更详细地解释了原因:
//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
exports is just 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;