MyFunction() vs window.setTimeout('MyFunction()', 0)?

В javascript есть ли какие-либо различия между этими двумя:

// call MyFunction normal way 

MyFunction();

// call MyFunction with setTimeout to 0 //

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

Причина, по которой я спрашивал, - это то, что недавно натолкнулась на ситуацию, когда код работает, только если я использую setTimeout(0) для вызова функции. Насколько я понимаю, setTimeout(0) точно такой же, как вызов функции напрямую, потому что вы не устанавливаете какую-либо задержку. Но из того, что я вижу, как он работает в коде, setTimeout(0), кажется, выполняется последним.

Может ли кто-нибудь точно определить, как setTimeout(0) действительно вызывается в порядке остальной части другого вызова функции?

Ответы

Ответ 1

setTimeout() всегда заставляет блок JavaScript быть поставлен в очередь для выполнения. Речь идет о том, когда он будет выполнен, что определяется предоставленной задержкой. Вызов setTimeout() с задержкой 0 приведет к тому, что интерпретатор JavaScript будет понимать, что он в настоящий момент занят (выполняет текущую функцию), и интерпретатор планирует запланировать блок script, который будет выполняться после того, как текущий стек вызовов пуст ( если нет других блоков script, которые также находятся в очереди).

Это может занять много времени, когда стек вызовов станет пустым, поэтому вы видите задержку в выполнении. Это в первую очередь связано с однопоточным характером JavaScript в контексте одного окна.

Для полноты, MyFunction() немедленно выполнит эту функцию. Там не будет очереди.

PS: Джон Ресиг имеет несколько полезных замечаний о том, как работает механизм синхронизации JavaScript.

PPS. Причина, по которой ваш код "работает", только когда вы используете setTimeout (fn(), 0), заключается в том, что браузеры могут обновлять DOM только тогда, когда текущий стек вызовов завершен, Поэтому следующий блок JavaScript распознает изменения DOM, что вполне возможно в вашем случае. Обратный вызов setTimeout() всегда создает новый стек вызовов.

Ответ 2

Я бы предположил, что таймаут начинается только тогда, когда страница полностью загружена, тогда как только простая "MyFunction()" будет выполняться, как только она будет обработана.

Ответ 3

Таймер будет пытаться выполнить, как только ваш текущий поток будет выполнен. Это зависит от того, где вы вызываете 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>

Если вы вызываете setTimeout внутри функции, которая возникает в результате события, например onload, то он будет ждать, пока функция обработчика события вернется:

<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, но они работают в другом файле, и единственный способ общения между ними - использовать прослушиватели событий, поэтому, пока вы можете отправлять сообщение, пока другой работает, он не получит этого до тех пор, пока оно не будет выполнено, или оно не проверит вручную сообщения.