我想获得一个带有全局对象的常量变量来动态使用它,但global.myconstant
不起作用,但global.myvar
起作用。
λ node
> const myconstant = true
undefined
> global.myconstant
undefined
> var myvar = true
undefined
> global.myvar
true
> global.const
undefined
我想做的事:
const myconstant = () => { console.log("ok const"); };
var myvariable = () => { console.log("ok var"); };
const watchlist = {
myconstant: "file1.html",
myvariable: "file2.html"
};
Object.keys(watchlist).forEach((taskName) => {
try {
global[taskName](); //doesn't work with const
} catch (e) {
console.error("error", taskName);
}
});
实际输出:
error myconstant
ok var
想要输出:
ok const
ok var
现场演示:https://repl.it/repls/SunnyScholarlyPasswords
如何使用字符串获取常量变量不使用var
替换const
。
只有用var
声明的变量才能隐式分配给全局对象。如果要创建不可重新分配的属性,则应使用Object.defineProperty
。例如,在浏览器中,引用window
而不是global
:
Object.defineProperty(
window,
'myconstant',
{
value: () => { console.log("ok const"); },
configurable: false
}
);
var myvariable = () => { console.log("ok var"); };
const watchlist = {
myconstant: "file1.html",
myvariable: "file2.html"
};
Object.keys(watchlist).forEach((taskName) => {
try {
window[taskName]();
} catch (e) {
console.error("error", taskName);
}
});
// Won't reassign, and will throw an error in strict mode:
window.myconstant = 'foo';
console.log(typeof window.myconstant);
configurable: false
是关键,尽管它是可选的——无论如何它都默认为false
。无法修改或删除不可配置的属性。
描述的行为对Node REPL来说是自然的,但对模块中评估的代码来说不是。模块范围内的变量不会泄漏到全局,因为它们是在模块范围内定义的,这适用于var
和const
。这就是节点模块中会发生的情况:
const myconstant = 1;
var myvariable = 2;
console.log(global.myconstant) // undefined
console.log(global.myvariable) // undefined
之所以在REPL中发生这种情况,是因为代码是在全局范围内求值的。所描述的行为可以通过间接eval
:在模块范围内复制
(0, eval)(`
const myconstant = 1;
var myvariable = 2;
`);
console.log(global.myconstant) // undefined
console.log(global.myvariable) // 2
这是var
和块范围变量(const
等)之间的区别。当在全局范围中定义时,var
会导致在全局变量(Node中的global
)上定义属性,而const
不会。
如果意图定义全局,则应将其定义为属性:
global.myconstant = 1;
global.myvariable = 2;
如果需要定义不会重新分配的全局变量,则应该使用描述符(正如另一个答案已经解释的那样):
Object.defineProperty(global, 'myconstant', {
value: 1,
configurable: false,
writable: false
});
通常不鼓励将全局用于本地目的,尤其是在Node等模块化环境中。