javascript for循环中的所有setTimeout都会立即发生

时间:2012-12-08 02:58:41

标签: javascript settimeout

此功能应从页面顶部向下滚动到215像素,延迟时间增加,以便第一个window.scrollTo事件发生在10ms,下一个发生在20ms,依此类推。
最后一行应该延迟2150毫秒,所以总共花费大约2秒钟 相反,它立即向下滚动215像素。

function scrollDown() {
  var yFinal=216, delay=0;
  for (y=0; y<yFinal; y++) {
    delay = delay+10
    setTimeout(function() {
      window.scrollTo(100,y);
    },delay);
  }
}
悲伤的脸。为什么呢?

[编辑:感谢您的帮助!我用它来写这个有点复杂的最终解决方案,我在这里提供给任何人扯掉它。它首先快速滚动,然后慢。正是我想要的。通过使用setInterval的setTimeout insteat,它可以让你更加控制速度曲线,因此你可以轻松地使它成倍地减速]

function showCategory(categoryId)
{
  var yInitial=document.body.scrollTop,
      yFinal=216,
      delay=0;

  if (yInitial<yFinal)
  {
    yInitial=(yFinal-yInitial)/1.3+yInitial;
    window.scrollTo(100, yInitial);

    for (var yCurrent = yInitial; yCurrent < yFinal; yCurrent+=2)
    {
      delay += 30;
      (function(position)
      {
        setTimeout(function()
        {
          window.scrollTo(100, position);
        }, delay);
      })(yCurrent);
    }
  }
}

2 个答案:

答案 0 :(得分:2)

超时不会一次性发生,它们会以您期望的时间发生。但是,它们都尝试滚动到由相同y变量表示的位置,因此它们都使用循环结束时y所具有的任何值。

通常的解决方法是引入一个闭包:

function scrollDown() {
    var yFinal = 216,
        delay = 0;

    for (var y = 0; y < yFinal; y++) {
        delay += 10;
        (function(position) {
            setTimeout(function() {
                window.scrollTo(100, position);
            }, delay);
        })(y);
    }
}​

(另请注意,您的y变量是全局的:您应该使用var声明它以使其成为本地变量。)

答案 1 :(得分:1)

您必须在匿名函数中包含setTimeout以按值传递y,而不是通过引用传递:{/ p>

(function(y) {
    setTimeout(function() {
        window.scrollTo(100,y);
    }, delay);
})(y);