2009-09-01 141 views
13

在JavaScript中,有没有这两者之间有什么不同:MyFunction()vs window.setTimeout('MyFunction()',0)?

// call MyFunction normal way 

MyFunction(); 

// call MyFunction with setTimeout to 0 // 

window.setTimeout('MyFunction()', 0); 

我问的原因是因为跨在那里,如果我使用setTimeout(0)调用该函数的代码只能局势近日来了。 据我的理解,setTimeout(0)与直接调用函数完全一样,因为你没有设置任何延迟。但从我看到它在代码中是如何工作的,setTimeout(0)似乎最后被执行。

有人可以澄清究竟如何setTimeout(0)真正按照其他函数调用的顺序调用吗?

+1

http:// stackoverflow。com/questions/779379/why-does-settimeoutfn-0-sometimes-help – 2009-09-01 02:33:00

回答

17

setTimeout()始终会使JavaScript块排队等待执行。这是由什么时候执行的问题,这是由提供的延迟决定的。 以延迟为0的方式调用setTimeout()将导致JavaScript解释器意识到它当前正忙(执行当前函数),并且解释器将调度当前调用堆栈为空时执行的脚本块(除非还有其他脚本块也在排队)。

调用堆栈变空可能需要很长时间,这就是为什么你看到延迟执行。这主要是由于单个窗口上下文中JavaScript的单线程性质。

为了完整起见,MyFunction()将立即执行该函数。将不涉及排队。

PSJohn Resig has some useful notes on how the JavaScript timing mechanism works

PPS:只有当您使用setTimeout(fn(),0)时,您的代码似乎“工作”的原因是因为只有当前调用堆栈完成时,浏览器才能更新DOM。因此,下一个JavaScript块会识别DOM更改,这在您的情况下很可能会发生。 setTimeout()回调总是创建一个新的调用堆栈。

3

我猜想超时只在页面完全加载时才开始,而只要一个普通的'MyFunction()'就会在处理完成后立即执行。

+1

这是正确的。无需猜测。 – 2009-09-01 02:29:15

+1

@Marius设置了一个测试页面并尝试它 - 内联函数将在顶部触发器声明的setTimeout(0)之前一直触发页面。 – 2009-09-01 02:38:32

+0

试过了,你是对的,并删除了我的评论,但不是在你看到它之前。 – Marius 2009-09-01 03:10:49

0

计时器会尝试执行一次当前线程完成。这取决于你调用window.setTimeout()的位置。如果它位于javascript标记中,但不在函数内部,那么一旦达到javascript标记的末尾,它就会被调用。例如:

<html> 
<script type="text/javascript"> 
setTimeout(function(){alert("hello")},0); 
var d=Number(new Date())+1000; 
while(Number(new Date())<d){ 

} 
alert("hi"); 
</script> 
</html> 

如果你调用从事件发生的历史的结果,例如onload事件函数里面的setTimeout的,那么它会等到事件处理函数返回:

<html> 
<script type="text/javascript"> 
document.addEventListener("mousedown",function(){ 
    setTimeout(function(){alert("hello")},0); 
    var d=Number(new Date())+1000; 
    while(Number(new Date())<d){ 

    } 
    alert("hi"); 
}, true); 
</script> 
</html> 

这是不可能的在另一个线程运行时让JavaScript中的一个线程等待。事件侦听器将等到当前线程完成后才开始运行。

唯一的例外是Web Workers,但它们运行在不同的文件中,并且它们之间进行通信的唯一方法是使用事件侦听器,因此虽然可以在另一个正在工作时发送消息,但它不会收到该消息直到完成,或者它手动检查消息。

+0

您所说的一切在一般意义上都是正确的(JavaScript是单线程的),但setTimeout(0)将在页面加载时触发,而不是在触击脚本块结尾时触发。 – 2009-09-01 02:37:31

相关问题