我在node.js编程,我遇到了一个小问题,这是由一些奇怪的引用问题引起的。
我使用以下代码:
for(j in groups){
console.log(j, somefunction(groups[j]))
}
在函数内部对数据做了一些时髦的事情,但之后我得到以下结果:
3 data
3 data
3 data
3 data
3 data
3 data
而不是
1 data
2 data
3 data
4 data
5 data
6 data
但它保留了正确的结果数量。
答案 0 :(得分:1)
您引用的代码没有按照您列出的内容执行,您可能会丢失一些简化问题的内容。
这段代码会产生你所描述的效果:
for(j in groups){
doSomething(function() {
// Callback for `doSomething`
console.log(j, somefunction(groups[j]));
});
}
请注意,现在我正在创建一个函数(无论doSomething
执行什么操作的回调),而不只是调用一个。
发生的原因是正在创建的函数对j
变量(以及执行上下文中的所有其他内容)都有持久引用,而不是副本在创建函数时的em> of it。它在执行上下文中称为闭包。所以你的循环运行,对doSomething
的一系列调用会启动一系列事情,然后在调用回调时,j
为3,所以它们对所有这些都是相同的。
通常的解决方案是创建一些函数来关闭一些在被调用之前不会改变的函数,如下所示:
for(j in groups){
doSomething(makeCallback(j));
}
function makeCallback(jarg) {
return function() {
console.log(jarg, somefunction(groups[jarg]));
};
}
现在,我们在回调中使用jarg
,而不是j
。因为jarg
是调用makeCallback
的上下文的一部分,所以它在我们创建函数和稍后调用它之间不会改变。
将数据绑定到函数的另一种方法是使用Function#bind
(有效地在后台创建一个闭包),这是NodeJS中可用的ES5功能,因为V8引擎具有它。这是看起来的样子:
for(j in groups){
doSomething(function(jarg) {
// Callback for `doSomething`
console.log(jarg, somefunction(groups[jarg]));
}.bind(this, j)); // <== Note the bind
}
或更不容易混淆(并且可能更有效):
for(j in groups){
doSomething(handler.bind(this, j));
}
function handler(jarg) {
// Callback for `doSomething`
console.log(jarg, somefunction(groups[jarg]));
}
关于闭包的更多信息:
答案 1 :(得分:0)
for(i in groups){
j = i
系统确实有效,但它不是最好的awnser
答案 2 :(得分:0)
这样做: -
for(var j in groups) { //Your code }
j未返回正确的值,因为您已在全局范围内指定了j。希望这有帮助!