Javascript node.js标准模块的全局变量?

Javascript node.js标准模块的全局变量?,javascript,module,node.js,global-variables,shared-libraries,Javascript,Module,Node.js,Global Variables,Shared Libraries,我知道全局变量是不好的 但是,如果在我的框架中的40个文件中使用node的模块“util”,将其声明为全局变量不是更好吗 util = require('util'); 在index.js文件中,而不是在40个文件中写入该行 因为我经常在每个文件中使用相同的5-10个模块,这将节省大量时间,而不是一直复制粘贴 在这种情况下,DRY不是很好吗?如果您将模块封装在块中(例如anon函数),您可以绑定到本地名称(通过参数或“var”),然后使用任意长(可能标记为“package”)名称(如果此时您甚

我知道全局变量是不好的

但是,如果在我的框架中的40个文件中使用node的模块“util”,将其声明为全局变量不是更好吗

util = require('util');
在index.js文件中,而不是在40个文件中写入该行

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


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

如果您将模块封装在块中(例如anon函数),您可以绑定到本地名称(通过参数或“var”),然后使用任意长(可能标记为“package”)名称(如果此时您甚至需要全局名称)

例如,我的模块通常类似于:

;(function ($, $exp, other) {
  $(...)
  other.xyz()
  $exp.MyExportedObject = ...;
})(jQuery, window, some_module.other_expression) // end module

我将jQuery与noConflict一起使用,这是前者,而后者表明您可以对任何表达式执行此操作——全局、require、computed、in-line等等。。。同样的“包装”方法可用于消除所有(或几乎所有)“特殊命名”全局性——全局性必须在某种程度上存在,然而,消除潜在冲突是一个非常大的胜利。

每个模块都应该是独立的。在每个模块的第一个模块之后,require不会花费任何费用

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

是的,即使在这种情况下,globals也是不好的。Globals几乎总是毁灭性的:可测试性、封装性和易维护性

2012年1月更新答案

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

因此,
global
对象仍然不是全局对象,因此不能作为全局对象使用

于2012年12月更新


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

您可以只拥有一个公共模块

common.js:

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

module.exports = Common;
app.js:

var Common = require('./common.js');
console.log(Common.util.inspect(Common));
中有一个关于全局对象的部分


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

我已成功地使用
过程
对象来传递我的配置对象。虽然在理论上与上面提到的问题(封装、可测试性等)完全相同,但当只使用非状态修改属性(基本上是一个带有原语的哈希表)时,它工作得很好。

我被这个线程中的答案弄糊涂了

我能做到这一点

文件: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可以访问该对象,而无需任何其他限定符


我正试图弄明白这一点(这让我从谷歌搜索中找到了这条线索),我想发布现在似乎对我有用的东西。自最初的答案以来,情况可能发生了变化。

全局对象与全局范围不同。您的赋值基本上是赋值给Nothiness。@Kato-在node.js中,全局对象不是您可以编写脚本的实际对象。它是node.js引擎中的一个内部对象。如果您想专门使用globals,您应该使用
process
,这相当于浏览器中的
窗口
。(虽然进程不包含
setTimeout
和其他“全局对象”,因为它们本身就是全局对象)。这是一个很好的想法。事实上,由于require的
导出
对象是缓存的,因此读取未使用require的文件不会产生额外的成本。(您可以通过在
common.js
中添加
console.log
行来测试它是否被缓存,并注意到无论您需要它多少次,
console.log
都只是第一次出现。)我不明白为什么这比在每个模块上只需要(…)要好,因为它是缓存的?有什么不同吗?@Kato:这更好(实际上很好),因为你现在不需要在每个文件中包含10个模块,而是只包含一个模块。正如您所说,它们是缓存的,因此这样做绝对不会过热。这造成了不必要的依赖。2.它节省了很少或创建了更多的键入,因为现在您使用的每个位置都是“Common.x.whater”,而不是“x.whater”,或者您将其别名为“var x=Common.x”,这与“var x=require(…)”类似,但如果您还不知道“x”是什么,则不太清楚。3.“x”的重构用法现在强制搜索Common.x和require(“x”),因为您不能确定每个人都使用Common.x。如果你经常使用它,为什么不制作一个片段“rutil>tab”?@user170934 1。这不是没有必要的。2.它避免了循环依赖性带来的许多麻烦,也节省了思考每个文件需要什么的时间,同时提供了一个在整个项目中使用的清晰名称空间<代码>让x=公共。x/c>也比“代码> x=要求())/>代码>语句中的许多行更干净。@ RADAASTASTHOBLUE,您也应该考虑节点不支持用户生成的Gulalal.Up生成的全局变量。你能详细解释一下吗?@TorValamo这似乎不对,我刚刚做了一个测试。分配给
global的任何内容。一个模块中的某些内容可以从另一个模块访问。因此,
global
保存进程(=应用程序)全局,而不是模块全局,并且所有会话的
global
都是相同的对象。至少对我来说是这样的。我能问你为什么这么说吗
require('test.js');
require('test2.js');