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),但当我弹出六个警告框时,警告框显示。 我做了一件非常愚蠢的错事吗?
提前致谢
答案 0 :(得分:12)
原因是你输入setTimeout
的函数是闭包,闭包对它们关闭的变量有持久引用,而不是副本在创建闭包时的值的em>。因此,所有这些函数都会尝试使用a
的相同值,它在循环完成后具有的值(例如6),因此它们将失败。
答案是让函数关闭而不会改变其他数据。通常的方法是使用一个工厂函数来创建并返回所需的实际函数,让它们接近你输入工厂函数的参数(不会改变),而不是你的循环变量。 E.g:
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
(以及context
,level
,和textArray
;如果他们改变了,你也会把它们传递出去。)
有关闭包的更多信息:Closures are not complicated
答案 1 :(得分:2)
这是非常常见的Javascript闭包问题。
循环中的变量a
在循环期间继续变化,因此回调中使用的值将是它具有的 last 值,而不是每个值的值通过循环的时间。
最简单的解决方法是:
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);
}
答案 2 :(得分:0)
试试这个......
for (a=0; a<6; a++)
{
(function(index)
{
setTimeout (function () { animatedDraw(context, 20+32*level[index],20*0, textArray[index]); }, timeArray[index]);
})(a)
}