我正在尝试动态创建指向对象的node.js变量。
我知道我可以使用eval在范围内动态创建变量:
var vars = ['a','b']
for(var n=0; n<vars.length; n++) {
eval('var '+vars[n]+' = '+n)
}
console.log(b) // prints 1
以上动态创建变量,并为它们提供vars
列表中索引的值。
但是如果我想将这些动态变量设置为对象引用呢?如下所示:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k) // create the variable dynamically
new Function('value', k+' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b) // undefined : (
我知道上面的原因不起作用 - new Function
创建的函数无法看到当前作用域,因此无法设置该值。有没有办法做我想做的事情,这样console.log(vars.a.b)
会打印“5”而不是“未定义”?
更新:
嗯,我错了,new Function
无法在本地范围内查看或修改变量,因为这样可行:
var obj = {}
eval('var x')
new Function('value', 'x = value')(obj)
obj.a = 5
console.log(x.a) // prints 5
所以现在我很困惑为什么我的循环似乎不起作用..
更新2:
我刚刚意识到我的代码实际上 在chrome的控制台中工作。但它不能在node.js中工作......
对PHIL的更新:
这是我的情况。我正在使用Parsimmon来构建解析器组合器。这就是这样做的:
var L = Parsimmon.createLanguage({
combinator1: function() {
return Parsimmon.string('hi')
},
combinator2: function() {
return L.combinator1.many()
}
})
我想在我编写的每个解析器组合器之前消除编写L.
的需要。我能做到这一点:
var combinator2 = L.combinator2
但这需要我为我编写的每个组合器添加一条额外的行。正如您所看到的,我无法使用with
,因为L
是在我能够编写with(L)
之后创建的,如果我在下面定义我的函数,那么在对象中使用它们,每次我写一个新的组合器时,我都会重复这些函数名称。
总而言之,我想循环遍历L
并将所有生成的解析器组合器放入范围内的一个漂亮的干净变量中,这样我就可以编写combinator1
而不是L.combinator1
(等)。
答案 0 :(得分:1)
IIUC,无论是否有更好的方法来实现您的目标,如果您只是删除动态'var '
上的Function
,它将在外部(全局)范围内运作。
变化:
new Function('value', k+' = value')(vars[k])
为:
new Function('value', k+' = value')(vars[k])
所以:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k) // create the variable dynamically
new Function('value', k+' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b)
您不希望在函数内声明具有局部作用域的新变量,您希望在外部作用域上操作。
更新以解决新问题
你的第一个循环确实有效。尝试对a
或b
进行反省;它们应该是预期的,分别为0和1。
根据信息更新2,这适用于Node.js
每https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function,Function
始终适用于全局范围。在Node中,这是global
和var
变量不是全局范围,而是模块的范围。要为Node修复此问题,您可以执行以下操作并省略eval
var
声明(该模块将覆盖您在Function
内可访问的全局范围的模块):
var vars = {a: {}, b:{}}
for(var k in vars) {
new Function('value', k +' = value')(vars[k]) // attempt to set the value
}
a.b = 5
console.log(vars.a.b) // 5
换句话说,内部函数设置自动变为可通过global
访问的变量,因此您的模块代码在没有任何模块范围的var
a
声明覆盖全局,您可以使用行a
设置全局a.b = 5
属性。
更新3
由于我刚刚在理解Function
时解决了您的问题,因此我提供了上述信息。根据您的后续评论(同样,在不说明其适用于您的特定用例的情况下),您可以通过eval
操作对象,如下所示:
var vars = {a: {}, b:{}}
for(var k in vars) {
eval('var '+k+' = vars["'+k+'"]')
}
a.b = 5
console.log(vars.a.b) // 5
但要重申其他人发出的警告 - 使用eval
通常不是一个好主意,并且当引用的变量包含任意用户数据时可能会很危险......
答案 1 :(得分:0)
更改此行:
docker-py
因为在你的情况下a未定义为什么它现在允许创建新属性
vars.a将返回一个对象,而不仅仅是一个vars属性。