node.js 标准module的全局变量?

IT技术 javascript module node.js global-variables shared-libraries
2021-02-28 05:57:39

我知道全局变量不好。

但是,如果我在框架的 40 个文件中使用节点的module“util”,将其声明为全局变量不是更好,例如:

util = require('util');

在 index.js 文件中而不是在 40 个文件中写入该行?

因为我经常在每个文件中使用相同的 5-10 个module,这样可以节省大量时间,而不是一直复制粘贴。

在这种情况下 DRY 不是很好吗?

6个回答

你可以只拥有一个通用模块。

常见的.js:

Common = {
  util: require('util'),
  fs:   require('fs'),
  path: require('path')
};

module.exports = Common;

应用程序.js:

var Common = require('./common.js');
console.log(Common.util.inspect(Common));
1. 这会造成不必要的依赖。2.它节省很少或创建更多的输入,因为现在你要么有“Common.x.whatever”而不仅仅是“x.whatever”你使用“whatever”的每个地方,或者你用“var x = Common.x”别名它就像 "var x = require(...)" 但如果你还不知道 "x" 是什么,就不太清楚了。3. 重构“x”的用法现在强制搜索 Common.x 和 require("x") 因为你不能确定每个人都使用 Common.x。如果您经常使用它,为什么不制作一个片段“rutil > tab”?
2021-04-20 05:57:39
这是一个绝妙的主意。事实上,因为 require 的exports对象被缓存了,所以在读取未使用的require 的文件时不会有额外的成本。(您可以通过向console.log添加一行来测试它是否已缓存,common.js并注意无论您需要多少次,console.log都只会在第一次发生。)
2021-04-21 05:57:39
@Kato:这更好(实际上很棒),因为您现在不必在每个文件中包含 10 个模块,而只需一个。正如您所说,它们已被缓存,因此这样做绝对不会过热。
2021-04-26 05:57:39
我不明白为什么这比每个模块上的 require(...) 更好,因为它被缓存了?有什么区别?
2021-04-29 05:57:39
@user170934 1. 这不是不必要的。2. 它省去了很多循环依赖的麻烦,省去了思考每个文件需要什么的时间,同时提供了一个清晰的命名空间,在整个项目中使用。let x = common.x也比许多x = require()语句行干净得多
2021-05-12 05:57:39

每个模块都应该是独立的。在每个模块的第一个需求之后,无论如何都不需要任何费用。

如果您想单独测试一个模块怎么办?您会遇到很多问题,因为它无法识别您的应用程序中的某些“全局”要求。

是的,即使在这种情况下,全局变量也很糟糕。全局变量几乎总是破坏:可测试性、封装性和易于维护。

2012 年 1 月更新答案

global对象现在是每个模块内的全局对象。因此,每次分配给模块内的全局变量(无作用域)时,它都会成为global该模块对象的一部分

global因此对象仍然不是global,并且不能这样使用。

2012 年 12 月更新

global对象现在在应用程序中具有全局作用域,可用于存储需要从所有模块访问的任何数据/函数。

@TorValamo 确实有点令人困惑。他们只用了 1 行来说明是什么global,而没有对它的工作原理进行任何解释,然后用 3 行来咆哮为什么需要它。仍然在这里他们说:“这些对象在所有模块中都可用。其中一些对象实际上不在全局范围内,而是在模块范围内......”这里是:“global: {Object} 全局命名空间对象。” ...无论如何,案例已结束,是时候再次更新答案了:) 你愿意还是我应该?
2021-04-15 05:57:39
@TorValamo 这似乎不正确,我刚刚做了一个测试。global.something在一个模块中分配的任何内容都可以从另一个模块访问。所以global持有进程(=应用程序)全局变量,而不是模块全局变量,并且global是所有会话的相同对象。至少这对我来说是这样的。我能问你为什么你说这global是模块的本地吗?你做了测试,如果是,那么测试是什么?
2021-04-24 05:57:39
@RadagasttheBrown 好吧,您还应该考虑该节点不支持用户制作的全局变量。
2021-04-25 05:57:39
用户制作的全局变量?你能详细说明一下吗?
2021-04-26 05:57:39
@esp 随时更新它,你似乎比我拥有更多关于它的最新信息;)
2021-05-09 05:57:39
global.util = require('util');

节点文档中有一个关于全局对象的部分

但是,应谨慎使用全局变量。通过向全局空间添加模块,您会降低可测试性和封装性。但在某些情况下,使用这种方法是可以接受的。例如,我将函数和对象添加到全局命名空间以在我的单元测试脚本中使用。

@Kato - 在 node.js 中,全局对象不是您可以编写脚本的实际对象。它是 node.js 引擎中的一个内部对象。如果要专门使用全局变量,则应使用process,相当于window浏览器中的 。(尽管该过程不包含setTimeout其他“全局对象”,因为它们本身就是全局对象)。
2021-04-16 05:57:39
全局对象与全局范围不同。你的任务基本上分配给虚无。
2021-05-05 05:57:39

我对这个线程中的答案感到困惑。

我能够做到这一点...

文件:test.js

global.mytest = {
    x: 3,
    y: function() { console.log('Works.'); }
};

文件:test2.js

console.log('Does this work?');
mytest.y();

文件:server.js

require('test.js');
require('test2.js');

它似乎可以满足所需的问题。第一个 require 将 mytest 对象放入全局范围,然后第二个 require 可以访问该对象而无需任何其他限定符。

我试图弄清楚这一点(这让我从谷歌搜索到了这个线程),我想发布现在似乎对我有用的东西。也许自最初的答案以来事情已经发生了变化。

是的,这在 Node.js 的最新版本中确实发生了变化。(虽然“最近”是相对而言的;那个版本的 Node 现在已经很旧了。)
2021-04-15 05:57:39

我已经成功地使用该process对象来传递我的配置对象。虽然理论上存在与上述完全相同的问题(封装、可测试性等),但它在仅使用非状态修改属性(基本上是带有原语的哈希表)时工作正常。

你能分享一些文章,解释什么是封装和可测试性
2021-05-10 05:57:39