Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «setTimeout(fn, 0)». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`setTimeout(fn, 0)`** не виконує функцію миттєво. **Ключове:** він лише ставить колбек `fn` у чергу макротасок, щоб той виконався після завершення поточного коду і всіх мікротасок.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Короткий відповідь `setTimeout(fn, 0)` **не виконує функцію миттєво**. Він просто **ставить колбек** `fn` **у чергу макротасок**, щоб він виконався **після завершення поточного коду і всіх мікротасок**. ## Приклад ```javascript console.log('A'); setTimeout(() => console.log('B'), 0); console.log('C'); ``` **Вивід:** ```javascript A C B ``` Чому не `A -> B -> C`? ## Що відбувається крок за кроком 1. `console.log('A')` - виконується одразу (у Call Stack). 2. `setTimeout(() => console.log('B'), 0)` - передає задачу у **Web API** (таймер із затримкою `0` мс). 3. Таймер миттєво "спрацьовує", і колбек додається в **чергу макротасок**. 4. JS продовжує виконувати поточний стек (`console.log('C')`). 5. Коли стек викликів порожній, **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()` - **макротаску**, - а **мікротаски завжди виконуються раніше**, ніж макротаски. ## Практичне застосування 1. **Відкласти виконання**, щоб не блокувати основний код: ```javascript setTimeout(() => { console.log('Виконається після основного коду'); }, 0); ``` 2. **Розірвати синхронний цикл**, щоб UI встиг оновитися: ```javascript for (let i = 0; i < 1e9; i++) {} // важка операція console.log('UI завис...'); setTimeout(() => { console.log('Тепер виконуємось після паузи'); }, 0); ``` 3. **Скинути стек** (наприклад, у рекурсивних обчисленнях): ```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)` завжди чекає, поки: 1. стек викликів очиститься, 2. мікротаски виконаються, 3. і лише потім - виконується `fn`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.