setTimeout()在循环中,奇怪的行为

时间:2014-04-23 13:10:41

标签: javascript

家伙!我是javascript的新手。我写了我的第一个程序并且已经坚持了它的行为:

var elements = document.getElementsByTagName("img");
for (var i = 0; i < elements.length; i++) {           
    if (i % 2 == 0) {
        elements[i].src = "img.jpg";
        for (var j = 0; j <= 1; j += 0.1) {
            setTimeout(increase_opacity(elements[i], j), 2000);
            // setTimeout(alert(j), 2000);
        }
    }
}

function increase_opacity(element, opacity) {
    element.style.opacity = opacity;
}

我无法看到不透明度发生变化,但在调试器下却发生了变化,因此setTimeout无法正常工作。如果我取消注释// setTimeout(alert(j), 2000);,我可以在每个循环步骤中看到不透明度更改和警报消息。那是为什么?

3 个答案:

答案 0 :(得分:1)

setTimeOut接受一个函数,你正在做的是将调用结果传递给increase_opacity。下面的代码应该适合您。请注意如何在匿名函数定义中包含increase_opacity。

var elements = document.getElementsByTagName("img");
for (var i = 0; i < elements.length; i++) {           
    if (i % 2 == 0) {
        elements[i].src = "img.jpg";
        for (var j = 0; j <= 1; j += 0.1) {
           (function(element, opacity) {
              setTimeout(function() { increase_opacity(element, opacity) } , 2000);
            })(elements[i], j);

            // setTimeout(alert(j), 2000);
        }
    }
}

以下是有关setTimeOut http://www.w3schools.com/jsref/met_win_settimeout.asp

的文档

答案 1 :(得分:1)

您需要将函数传递给setTimeout()。你正在做的是立即调用increase_opacity然后将返回值传递给setTimeout()

由于您想要使用特定参数调用函数,您可以使用闭包来记录ij的当前值:

setTimeout((function(a, b) {
  return function() {
    increase_opacity(a, b);
  };
})(elements[i], j), 2000);

答案 2 :(得分:0)

您是否知道setTimeout()不是阻止通话?您的脚本不会停留在setTimeout()函数,而是继续执行。所以,这里发生了什么:

1)你的代码开始循环;
2)当它进入setTimeout()时,它启动计时器并继续前进;
3)对每个元素重复步骤2; (请注意,步骤2和3将在几毫秒内执行)
4)所有计时器到期,所有指令都一次执行。

为了避免这种情况,你应该写一些类似的东西:

var elements = document.getElementsByTagName("img");
for (var i = 0; i < elements.length; i++) {           
    if (i % 2 == 0) {
        elements[i].src = "img.jpg";
        setTimeout(function(){increase_opacity(elements[i],0);}, 2000);
    }
}

function increase_opacity(element, opacity) {
    element.style.opacity = opacity;
    if (opacity < 1) setTimeout(function(){increase_opacity(element, opacity+0.1);},2000);
}

NB:在处理setTimeout()时,您应该在使用参数调用函数时避免使用该表示法。你应该总是使用它:

setTimeout(function(){yourFunctionName(arg1, arg2, arg3);});

NB 2: setTimeout(alert(j),2000);甚至没有等待2秒钟出现。就像我上面说的那样,在处理setTimeout()时应该使用匿名函数。它可能因此而给人留下了印象,但它是一种小故障IMO。