【问题标题】:Javascript's setTimeout function not callingJavascript setTimeout函数未调用
【发布时间】:2008-12-04 17:26:22
【问题描述】:

setTimeout 函数似乎总是给我带来麻烦。现在我有一个递归函数(通过 setTimeout 调用自身)并更改元素高度。

该函数被发送两个参数:要更改的元素和该元素的最大高度。该功能的目的是展开元素,或以恒定的速度“向下滑动”。我知道我可以用 jQuery 解决这个问题,但我正在尝试我自己的函数。

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    {
        var factor = 10;
        var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
        element.style.height = new_height + 'px';

        var func_call = 'slide_down(' + element + ', ' + max_height + ');';
        window.setTimeout(func_call, 10);
    }
}

我已经测试了函数最初被调用时的参数。 max_height 设置为 20,因为它是元素所需的高度(我从 .scrollHeight 获得了这个值)。

函数完成后,我想让它自己调用,直到 max_height 是元素的高度。我通过这个 setTimeout 调用来做到这一点:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);

而且它不工作。这确实有效:

var func_call = 'alert(1);';
window.setTimeout(func_call, 10);

我也试过把函数调用直接放到setTimeout语句中,还是不行。

请注意,元素的高度在第一次迭代时会改变,函数只是从不调用自身。所以元素变量设置正确,我使用 alert() 显示 max_height 也是正确的。

alert(func_call);

提醒:

slide_down([object HTMLParagraphElement], 20);

【问题讨论】:

    标签: javascript settimeout


    【解决方案1】:

    当你这样做时:

    var func_call = 'slide_down(' + element + ', ' + max_height + ');';
    

    您正在将元素转换为字符串,因此您的超时将如下所示

    slide_down("[Object]", 100);
    

    这显然行不通。

    你应该做的是创建一个闭包——这有点复杂,但基本上你创建了一个函数,旧函数中的局部变量在新函数中仍然可用。

    function slide_down(element, max_height)
    {   
        if(element.clientHeight < max_height)
        {
            var factor = 10;
            var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
            element.style.height = new_height + 'px';
    
            var func = function()
            {
                slide_down(element, max_height);
            }
    
            window.setTimeout(func, 10);
        }
    }
    

    对于超时来说,10 有点短 - 我建议至少使用 50。

    【讨论】:

    • 谢谢。我正在寻找它。
    【解决方案2】:

    首先,如果你不改变周期,这个“现在我有一个递归函数(通过 setTimeout 调用自身)”向我尖叫 setInterval

    其次,这是因为元素引用在字符串 concat 中丢失,因为 element.toString() 将是“[object]”。尝试传入一个您可以重新查找的 id,将引用存储到一个级别,或者(正如我刚刚看到的 matt b 指出的)扩展的方法形式。

    【讨论】:

      【解决方案3】:

      编写方法的更微妙的方式(作为 Gregs 答案的扩展):

      function slide_down(element, max_height)
      {   
          if(element.clientHeight < max_height)
          { return; }
      
          var factor = 10,
              new_height = element.clientHeight + factor,
              f = arguments.callee;
      
          if( new_height > max_height )
          { new_height = max_height; }
      
          element.style.height = new_height + 'px';
      
          window.setTimeout(function() { f(element, max_height); }, 10);
      }
      

      此示例代码的真正优势在于使用了arguments.callee。如果您决定重命名它,这样您就不会破坏您的功能。我还简化了new_height 的赋值。旧代码中的问题是您执行了两次element.clientHeight + factor,这有点不必要。并不是说在这种情况下它对你的表现有任何明显的影响。但最好避免一遍又一遍地计算相同的东西,而只是将结果存储起来以备后用。

      【讨论】:

        【解决方案4】:

        我也有类似的经历。当您下次传递元素时,它会在函数调用中转换为字符串,因此当函数运行时,它会尝试查找名为 [object].string 或其他内容的元素,而不是您想要的。

        尝试更改您的函数参数以获取元素的 id 并在函数内部执行 document.getElementById() 调用。

        【讨论】:

          【解决方案5】:

          你的代码的问题是你没有传递元素参数。

          代替:

          var func_call = 'slide_down(' + element + ', ' + max_height + ');'; window.setTimeout(func_call, 10);

          尝试使用匿名函数:

          window.setTimeout(function() { slide_down(元素,最大高度) }, 10);

          @matt.b: IE 不支持传入 setTimeout 调用的参数(你的做法)。

          【讨论】:

            【解决方案6】:

            两件事:

            1. 有另一种调用setTimeout() 的方法,您可以在其中传递函数和参数,而不是要执行的字符串。其实the Gecko DOM manual states那个你的版本调用setTimeout()是不推荐的。

            代替:

            var func_call = 'slide_down(' + element + ', ' + max_height + ');';
            window.setTimeout(func_call, 10);
            

            试试这个:

            window.setTimeout(slide_down, 10, element, max_height);  
            

            更新:正如 RoBorg 所说,这在 IE 中可能不起作用,所以你不妨忽略它。


            2. 我感觉从 setTimeout() 自身调用的函数中调用 setTimeout() 要么是不允许的,要么不能正常工作。我假设您正在链接这样的调用,因为您希望代码重复执行?如果是这样,这就是window.setInterval() 的用途。

            【讨论】:

            • 嗯,我想我从来没有遇到过这种语法,因为“请注意,在第一种语法中将附加参数传递给函数在 Internet Explorer 中不起作用”。您的第一个链接出现在 404 之前,因此您要么进行了编辑,要么出现了故障。 -1 移除
            • 我修复了链接问题,https 格式不正确。谢谢。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-26
            相关资源
            最近更新 更多