Javascript setTimeout函数没有调用

时间:2008-12-04 17:26:22

标签: javascript settimeout

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);

6 个答案:

答案 0 :(得分:19)

执行此操作时:

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。

答案 1 :(得分:3)

首先,这个“现在我有一个递归的函数(通过setTimeout调用自己)”“如果你没有改变周期,就会尖叫 setInterval 。” / p>

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

答案 2 :(得分:2)

编写方法的一种更微妙的方式(作为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,这有点无关紧要。并不是说在这种情况下它对你的表现有任何明显的影响。但是,避免一遍又一遍地计算相同的事情总是好的,但只是存储结果供以后使用。

答案 3 :(得分:1)

我有类似的经历。当你下次传递元素时,它会在函数调用中转换为字符串,所以当函数运行时,它会尝试找到一个名为[object] .string的元素,而不是你想要的东西。< / p>

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

答案 4 :(得分:1)

您的代码存在的问题是您无法传递元素参数。

而不是:

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

window.setTimeout(func_call, 10);

尝试使用匿名函数:


window.setTimeout(function() {
    slide_down(element, max_height)
}, 10);

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

答案 5 :(得分:0)

两件事:

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()的用途。