2011-06-15 229 views
2
var a=0; 
setTimeout (function() { animatedDraw(context, 20+32*level[0],20*0, textArray[0]); }, timeArray[0]); 
setTimeout (function() { animatedDraw(context, 20+32*level[1],20*1, textArray[1]); }, timeArray[1]); 
setTimeout (function() { animatedDraw(context, 20+32*level[2],20*2, textArray[2]); }, timeArray[2]); 
setTimeout (function() { animatedDraw(context, 20+32*level[3],20*3, textArray[3]); }, timeArray[3]); 
setTimeout (function() { animatedDraw(context, 20+32*level[4],20*4, textArray[4]); }, timeArray[4]); 
setTimeout (function() { animatedDraw(context, 20+32*level[5],20*5, textArray[5]); }, timeArray[5]); 

for (a=0; a<6; a++) 
    setTimeout (function() { animatedDraw(context, 20+32*level[a],20*0, textArray[a]); }, timeArray[a]); 

我的代码的第一部分是工作的部分。第二部分没有出现。我正在绘制一个画布(HTML 5),但是当我弹出六个警报框时,警示框显示出来。 我在做什么非常愚蠢的错误?JavaScript,for循环将不起作用

在此先感谢

回答

12

的原因是,你送入setTimeout的函数都是闭包和闭包有一个持久参考他们收,较变量,而不是它们的值的副本为什么时候关闭创建。因此,所有这些函数都会尝试使用相同的值a,在循环完成后(例如6)它具有的值,因此它们将失败。

答案是让函数关闭一些其他数据,而不会改变。通常的做法是创建一个工厂函数,它可以创建并返回所需的实际函数,让它们关闭您提交给工厂函数(不会更改)的参数,而不是您的循环变量。例如:

for (a=0; a<6; a++) { 
    setTimeout(makeTimerFunction(a), timeArray[a]); 
} 

function makeTimerFunction(index) { 
    return function() { 
     animatedDraw(context, 20+32*level[index],20*0, textArray[index]); 
    }; 
} 

正如你可以看到,现在正由makeTimerFunction创建的功能关闭了index而非a(并且还在contextleveltextArray,你会通过那些,以及如果他们改变)。

更多关于关闭:Closures are not complicated

+0

我会接受你的答案时,我可以。谢谢,这正是我的问题!当我减少我的循环时,最后的声明显示。 – Hidde 2011-06-15 18:49:29

+1

@Michael:不,这没有帮助,因为如果它在函数内部,它在函数运行时仍然使用'a'。你需要一个工厂或类似的东西;我已经添加了一个例子。 – 2011-06-15 18:50:38

+0

@Hidde:很高兴帮助。我添加了一个如何处理它的例子。 – 2011-06-15 18:51:05

2

这是很常见的JavaScript关闭问题。

你的变量a在循环继续循环过程中发生变化,所以在回调中使用的值将是最后价值它有,而不是价值它发生在循环每次都有。

最简单的解决方法是这样的:

function timer_setup(a) { 
    setTimeout(function() { 
     animatedDraw(context, 20+32*level[a],20*0, textArray[a]); 
    }, timeArray[a]); 
}; 

for (a=0; a<6; a++) { 
    timer_setup(a); 
} 
0

尝试......

for (a=0; a<6; a++) 
{ 
    (function(index) 
    { 
     setTimeout (function() { animatedDraw(context, 20+32*level[index],20*0, textArray[index]); }, timeArray[index]); 
    })(a) 
} 
+0

这将创建并丢弃每个循环的工厂函数,这是浪费。可能无害,但浪费。 – 2011-06-15 19:01:44

+0

我同意,我认为你的解决方案要好得多。 – MillsJROSS 2011-06-15 19:18:49