Javascript,for循环不起作用

时间:2011-06-15 18:44:56

标签: javascript arrays for-loop

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),但当我弹出六个警告框时,警告框显示。 我做了一件非常愚蠢的错事吗?

提前致谢

3 个答案:

答案 0 :(得分:12)

原因是你输入setTimeout的函数是闭包,闭包对它们关闭的变量有持久引用,而不是副本。因此,所有这些函数都会尝试使用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(以及contextlevel,和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)
}