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