setTimeout(fn, 0)
Короткий відповідь
setTimeout(fn, 0) не виконує функцію миттєво.
Він просто ставить колбек fn у чергу макротасок, щоб він виконався після завершення поточного коду і всіх мікротасок.
Приклад
javascript
console.log('A');
setTimeout(() => console.log('B'), 0);
console.log('C');Вивід:
javascript
A
C
BЧому не A -> B -> C?
Що відбувається крок за кроком
console.log('A')- виконується одразу (у Call Stack).setTimeout(() => console.log('B'), 0)- передає задачу у Web API (таймер із затримкою0мс).- Таймер миттєво "спрацьовує", і колбек додається в чергу макротасок.
- JS продовжує виконувати поточний стек (
console.log('C')). - Коли стек викликів порожній, Event Loop бере задачу
() => console.log('B')із черги і виконує її.
Чому навіть 0 не виконується одразу
Тому що в JavaScript усе працює через Event Loop, і він ніколи не перериває поточний стек викликів.
Навіть якщо затримка
0, колбек все одно повинен зачекати, поки стек звільниться.
Тобто setTimeout(fn, 0) - це спосіб відкласти виконання функції до наступної ітерації Event Loop.
Приклад з promise (мікротаска)
javascript
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');Порядок:
javascript
end
promise
timeoutПояснення:
Promise.then()створює мікротаску,setTimeout()- макротаску,- а мікротаски завжди виконуються раніше, ніж макротаски.
Практичне застосування
- Відкласти виконання, щоб не блокувати основний код:
javascript
setTimeout(() => {
console.log('Виконається після основного коду');
}, 0);- Розірвати синхронний цикл, щоб UI встиг оновитися:
javascript
for (let i = 0; i < 1e9; i++) {} // важка операція
console.log('UI завис...');
setTimeout(() => {
console.log('Тепер виконуємось після паузи');
}, 0);- Скинути стек (наприклад, у рекурсивних обчисленнях):
javascript
function nextStep() {
setTimeout(nextStep, 0); // кожне повторення - нова ітерація Event Loop
}
nextStep();Підсумок
| Параметр | Значення |
|---|---|
| Що робить | Ставить колбек у чергу макротасок |
| Коли виконується | Після поточного стеку і всіх мікротасок |
| Затримка "0" | Не миттєво, а в наступному циклі Event Loop |
| Черга | Макротаски |
| Повертає | ID таймера (можна скасувати через clearTimeout) |
Візуально
javascript
[Call Stack] → виконується поточний код
[Microtask Queue] → promise та queueMicrotask
[Task Queue] → setTimeout(fn, 0)setTimeout(fn, 0) завжди чекає, поки:
- стек викликів очиститься,
- мікротаски виконаються,
- і лише потім - виконується
fn.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.