Javascript Node.js中的仅模块作用域
我试图让一个函数在模块的顶级作用域中设置一个变量,但不让它泄漏到全局作用域中(因为…不好)。起初,我认为模块中的隐式变量声明将保留在模块中,但它似乎也会转到调用模块的脚本中 例如(aModule.node.js): 然后要求它:Javascript Node.js中的仅模块作用域,javascript,node.js,scope,globals,Javascript,Node.js,Scope,Globals,我试图让一个函数在模块的顶级作用域中设置一个变量,但不让它泄漏到全局作用域中(因为…不好)。起初,我认为模块中的隐式变量声明将保留在模块中,但它似乎也会转到调用模块的脚本中 例如(aModule.node.js): 然后要求它: var aModule = require('./aModule.node.js'); console.log(globalToEveryone); //outputs "true" console.log(typeof onlyToThisModule); //
var
aModule = require('./aModule.node.js');
console.log(globalToEveryone); //outputs "true"
console.log(typeof onlyToThisModule); //outputs "undefined"
我想做的是在
createAGlobal
中声明一个不会泄漏到全局范围的变量。我希望将它保留在调用它的函数的范围内。我知道我可以把它放在模块本身的var语句中,但是我只希望在有人执行函数时声明变量。有没有办法实现这种类型的作用域?为什么要求只有在有人调用函数时才声明变量?如果这不是严格的要求,那么您可以在模块范围内声明它,并在功能范围内初始化它:
var onlyToThisModule; // currently `undefined`
function initVar() {
onlyToThisModule = true;
}
console.log(onlyToThisModule); // undefined
initVar();
console.log(onlyToThisModule); // true
。。。另一方面,如果您确实希望仅在函数中声明变量,并且使其对模块的其余部分可用,则可以将其创建为类属性:
function myClass() {
this.onlyToThisModule = true;
}
var mc = new myClass();
console.log(mc.onlyToThisModule);
。。。但这仍然会通过函数的中介将变量暴露给调用模块
如果这两个都不适合您的情况,那么您必须提供更多详细信息。当您定义一个变量而不使用
var
时,它将被置于全局范围内,并且有一些超出此注释范围的其他细微差别。它不是一个“隐式变量”
无论如何,模块本身可以通过require()
从任何地方访问,因此您无需将任何内容设置为全局:
按量
exports.globalToEveryone = true;
在另一个模块中
var globalVal = require('aModule').globalToEveryone;
要扩展:
如果您想控制对它的访问,那么您想从任何地方访问的值几乎肯定不应该是全局的。出于您的目的,更好的答案可能是使用访问器方法:
var globalToEveryone = undefined;
exports.globalToEveryone() = function() {
if (globalToEveryone !== undefined) {
return globalToEveryone;
} else {
// what happens if it hasn't been set yet?
}
}
当您对值感兴趣时,可以使用
var localVersion = require('aModule').globalToEveryone();
您会发现,尽管您必须多键入一点才能获得值,但您将拥有更多可维护的代码。好的。谢谢你的回答,但是经过很多的烦恼和研究,我想做我想做的事情,但是我离我的项目足够近了 死胡同:我能够使用V8的堆栈跟踪和假装错误来访问作用域链上变量的内容。不过,我还是没能把它写到最上面的范围。而且这有点疯狂。我也尝试了一些
Object.defineProperty
的把戏,但我从来都不能让它完全按照需要工作
就我而言,它可以将所有东西放入一个对象中,然后使用和
,这比globals稍微小一些。对于我需要的情况,它工作得很好。那么像这样,
var local = {
a : '1',
b : '2',
c : '3'
};
function contained() {
with (local) {
console.log(a,b,c);
}
}
console.log(typeof a) //undefined
contained();
现在,我将通过模块传递本地对象,并让脚本或其他模块在需要时使用
和
。没有我所希望的那么纯粹。我还认为隐式变量应该是模块的局部变量,因为您可以使用global.foo
(我知道,这不会发生,会破坏互联网等等)您可以先创建一个空变量,然后在调用函数后用数据填充它<代码>var全局;function(){global=true}Yes,但这只适用于特定的上下文。所以,如果您有第三个模块,它需要aModule.node.js并执行createAGlobal(),这无法实现我的目标。这对我的情况没有帮助。因此,我希望只有在调用函数createAGlobal
之后,才能由模块本身声明变量名。我应该注意到,这是一个大约50的变量,我这样做,确切的名称非常重要。我认为你的问题的答案在于另一个问题:如果代码的另一部分在设置变量之前使用该变量,你希望发生什么?在这种情况下,简单的答案是在设置变量之前声明它为未定义。谢谢不能满足我的需要。第一个示例不是模块化的-我需要能够在多个不同的模块中调用createAGlobal
,并在init失败之前声明变量。第二个例子更接近,但变量名并不是我所需要的。正如我在另一个答案的评论中提到的,这是我需要用确切名称声明的大约50个变量中的一个。我使用的是您示例中的变量名称。我无法预测哪些变量名可能适合您的应用程序,所以您只能自己管理它。如果您希望在其他模块中包含您的模块,并且每个调用模块都有自己的变量副本,那么第二个选项就是您要查找的。如果您只是希望在调用该变量的第一个模块调用该变量之前,该变量是未定义的,然后每个人都可以使用同一个变量,第一个例子就是这样做的。如果你想要别的东西,那我就不明白了。这是关于特定的命名——所以我不能用类来添加这些属性,因为我需要“onlyToThisModule”是“onlyToThisModule”,而不是“mc.onlyToThisModule”或“rats.onlyToThisModule”或“hairball.onlyToThisModule”,如果这有意义的话。我假设你是说你需要每个调用模块都有自己的版本分配的变量是多少?如果是这样,那么您就卡住了,如果它需要在函数返回之后继续存在,那么它需要是一个类属性。如果它不需要在函数结束后继续存在,那么只需在函数内部声明它,然后使用它就可以了。如果每个调用模块都可以访问变量的同一个副本,那么只需在模块范围内声明它,但在调用函数之前不分配它,就可以了
var local = {
a : '1',
b : '2',
c : '3'
};
function contained() {
with (local) {
console.log(a,b,c);
}
}
console.log(typeof a) //undefined
contained();