Как ответить
JavaScript — однопоточный и синхронный язык в своей основе. Это значит, что в каждый момент времени выполняется только одна инструкция, и код выполняется последовательно, строка за строкой. Но за счёт механизма событийного цикла (event loop) и асинхронных API браузера (setTimeout, fetch, промисы) он может обрабатывать неблокирующие операции и «делать вид», что работает многопоточно.
Синхронность проявляется в том, что если вы напишете простой цикл, он заблокирует выполнение до завершения. Например:
console.log('A');
for (let i = 0; i < 1e9; i++) {} // долгая операция
console.log('B');
// Вывод: A, пауза, BАсинхронность же достигается через коллбэки, промисы и async/await. Они не создают новые потоки, а откладывают выполнение кода в очередь задач (task queue), которую обрабатывает event loop после завершения текущего синхронного кода.
Ключевые механизмы:
- Стек вызовов (call stack) — место, где выполняются синхронные функции.
- Web API (или Node.js API) — предоставляют асинхронные операции (таймеры, запросы).
- Очередь микрозадач (microtask queue) — для then/catch, async/await, MutationObserver.
- Очередь макрозадач (macrotask queue) — для setTimeout, setInterval, событий DOM.
- Event loop — бесконечный цикл: если стек пуст, берёт первую микрозадачу, затем одну макрозадачу.
Пример с асинхронностью:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Вывод: 1, 4, 3, 2
// Пояснение: синхронный код (1,4) выполняется первым, затем микрозадача (3), затем макрозадача (2).Для junior важно понимать, что однопоточность накладывает ограничения — тяжёлые вычисления блокируют интерфейс. Поэтому для CPU-интенсивных задач используют Web Workers (они выполняются в отдельных потоках, но не имеют доступа к DOM).