我正在尝试使用函数在模块的顶级范围内设置变量,但不要将其泄漏到全局范围内(因为......坏)。起初我以为模块中的隐式变量声明会保留在模块中,但它似乎也适用于调用模块的脚本。
以示例(aModule.node.js)为例:
var
onlyToThisModule = true;
function createAGlobal() {
//creates a implicit var unfortunately
globalToEveryone = true;
}
createAGlobal(); //this will now appear in the global scope for the script that require() it. eeek.
console.log(onlyToThisModule);
exports = createAGlobal;
然后要求它:
var
aModule = require('./aModule.node.js');
console.log(globalToEveryone); //outputs "true"
console.log(typeof onlyToThisModule); //outputs "undefined"
我想要做的是在createAGlobal
中声明一个不会泄漏到全局范围内的变量。我想将它保留在调用它的函数的范围内。我知道我可以把它放在模块本身的var语句中,但是我只想在有人执行该函数时声明变量。有没有办法实现这种类型的范围?
答案 0 :(得分:1)
当您在不使用var
的情况下定义变量时,它将被置于全局范围内,并且具有超出此注释范围的其他一些细微差别。它不是'隐含变量'。
无论如何,可以通过require()
从任何地方访问模块本身,因此您不需要创建任何全局:
在aModule中
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();
你会发现虽然你需要多输入一点才能得到这个值,你将拥有更多可维护的代码。
答案 1 :(得分:0)
为什么要求变量只有在有人调用函数时才会声明?如果这不是严格要求,那么您可以在模块范围内声明它,并在您的函数范围内初始化它:
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);
...但是这仍然会通过函数的中介将变量暴露给调用模块。
如果这些都不适合您的情况,那么您将需要提供更多详细信息。
答案 2 :(得分:0)
好的。感谢您的回答尝试,但经过多次烦恼和研究后,I don't think it is possible完全按照我的要求去做,但我已经足够接近我的项目了。
死胡同:我能够使用V8的堆栈跟踪访问作用域链中的变量内容并伪造错误。我无法设法写入链中的范围。再加上这有些疯狂。我也试图做一些Object.defineProperty
诡计,但我从来没有按照要求完全工作。
出于我的目的,它可以将所有内容放入一个对象中然后使用with
,这比全局变量稍微不那么邪恶。对于我需要的情况,它工作正常。所以,像这样:
var local = {
a : '1',
b : '2',
c : '3'
};
function contained() {
with (local) {
console.log(a,b,c);
}
}
console.log(typeof a) //undefined
contained();
现在我将只通过模块传递本地对象,并让脚本或其他模块在需要时使用with
。不像我希望的那样语法纯粹。我还认为隐式变量应该只对模块本地化,因为你可以使用global.foo
访问全局变量(我知道,不会发生,会打破互联网等等)