我如何dynamic地在node.js中的当前作用域中dynamic创build一个variables?
我试图dynamic创build指向对象的node.jsvariables。
我知道我可以使用evaldynamic创build一个variables:
var vars = ['a','b'] for(var n=0; n<vars.length; n++) { eval('var '+vars[n]+' = '+n) } console.log(b) // prints 1
上面的代码dynamic地创build了variables,并给它们赋值了vars
列表中的任何索引。
但是如果我想将这些dynamicvariables设置为对象引用呢? 像下面这样:
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 } ab = 5 console.log(vars.ab) // undefined : (
我知道为什么上述不起作用 – 由new Function
函数创build的new Function
不能看到当前范围,所以不能设置值。 有没有办法做我想做的事情,这样console.log(vars.ab)
会打印“5”,而不是“undefined”?
更新:
嗯,我错了, new Function
无法看到或修改本地范围内的variables,因为这个工程:
var obj = {} eval('var x') new Function('value', 'x = value')(obj) obj.a = 5 console.log(xa) // prints 5
所以现在我很困惑为什么我的循环以上似乎不工作..
更新2:
我只是意识到我的代码实际上在Chrome的控制台中工作。 但它不能在node.js中工作…
更新只是菲尔:
这是我的情况。 我使用Parsimmon来构buildparsing器组合器。 这是如何完成的:
var L = Parsimmon.createLanguage({ combinator1: function() { return Parsimmon.string('hi') }, combinator2: function() { return L.combinator1.many() } })
我希望在我编写每个parsing器组合器之前,不需要写L.
我可以这样做:
var combinator2 = L.combinator2
但是,这将需要我为我写的每个combinator添加一个额外的行。 正如你所看到的,我不能使用with
因为L
是在我可以写with(L)
之后创build的,如果我在下面定义我的函数然后在对象中使用它们,我回来复制这些函数名每次我写一个新的combinator。
所以总结一下,我想通过L
循环,并把所有生成的parsing器组合器放在一个很好的干净的variables范围内,所以我可以写combinator1
而不是L.combinator1
(etc)。
IIUC,无论是否有更好的方法来实现你的目标,如果你只是在dynamicFunction
删除'var '
,它将在外部(全局)范围上操作。
更改:
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 } ab = 5 console.log(vars.ab)
你不想在函数内部声明一个局部范围的新variables,你想在外部范围上操作。
更新来解决新的问题
你的第一个循环确实有效。 试着反思a
或b
; 他们分别是0和1。
根据信息更新2,这是为Node.js
根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function , Function
始终在全局范围内工作。 在Node中,这是global
, var
variables不是全局作用域,而是模块的作用域。 为了解决这个节点,你可以做下面的事情,并省略你的eval
var
声明(这是重写模块的全局范围,你可以访问Function
):
var vars = {a: {}, b:{}} for(var k in vars) { new Function('value', k +' = value')(vars[k]) // attempt to set the value } ab = 5 console.log(vars.ab) // 5
换句话说,内部函数设置的variables可以通过global
自动访问,所以你的模块代码,在没有任何覆盖全局的模块范围的var
声明的时候,你可以设置全局的a
属性,就像ab = 5
。
更新3
由于我刚刚在理解Function
解决了你的问题,所以我给了上面的信息。 根据你的后续评论(再次,没有说明它是否适合你的特定用例),你可以通过eval
对对象进行操作,如下所示:
var vars = {a: {}, b:{}} for(var k in vars) { eval('var '+k+' = vars["'+k+'"]') } ab = 5 console.log(vars.ab) // 5
改变这一行:
from : ab = 5 to vars.ab = 5
因为a在你的情况下是未定义的,这就是为什么现在允许创build一个新的属性
vars.a将返回一个对象,不仅是一个variables属性。