Кратко
JavaScript выполняет код построчно в одном потоке. Каждый вызов функции добавляется в стек вызовов (call stack). Если операция занимает много времени — она блокирует весь интерфейс. Асинхронные механизмы позволяют запускать долгие операции, не блокируя основной поток.
Подробно
Call Stack (стек вызовов):
Когда JavaScript выполняет функцию, он помещает её в стек. Когда функция завершается — она удаляется из стека.
function first() { console.log('first'); } function second() { first(); console.log('second'); } second();
// Стек: [second] → [second, first] → [second] → [] // Вывод: first, second
Синхронный код выполняется последовательно. Если функция выполняется долго — весь код «ждёт».
Пример блокировки: function heavyComputation() { // Цикл на 5 секунд const start = Date.now(); while (Date.now() - start < 5000) {} console.log('Готово!'); }
heavyComputation(); // 5 секунд блокировки! console.log('Это выведется ПОСЛЕ'); // через 5 секунд
Почему это проблема:
- Браузер не может обрабатывать клики
- Анимации останавливаются
- Страница «зависает»
В браузере есть один основной поток (main thread). JavaScript-код и обработка событий работают в одном потоке. Поэтому долгая синхронная операция блокирует всё.
Асинхронные механизмы: Браузер предоставляет механизмы для неблокирующего выполнения:
- Таймеры (setTimeout)
- Сетевые запросы (fetch)
- События (addEventListener)
Эти операции выполняются параллельно основному потоку, а результат передаётся обратно через callback.
Ментальная модель
Call stack — как стопка тарелок. Каждый вызов функции — новая тарелка сверху. Когда функция завершается — тарелка убирается. Если стопка слишком высокая — она падает (Stack Overflow). Блокирующий код — как тяжёлая тарелка, которую невозможно убрать, пока она не «прогрузится».
Примеры
**Самый простой:**
console.log('1');
console.log('2');
console.log('3');
// Вывод: 1, 2, 3
// Синхронный код: строки выполняются по порядку.Синхронный код выполняется последовательно, строка за строкой.
**Простой:**
function a() { console.log('a'); }
function b() { a(); console.log('b'); }
function c() { b(); console.log('c'); }
// Стек: [c] → [c, b] → [c, b, a] → [c, b] → [c] → []
// Вывод: a, b, cВложенные вызовы: стек растёт при входе и уменьшается при выходе.
**Реальный пример:**
// Блокировка UI:
const button = document.querySelector('#myButton');
button.addEventListener('click', () => {
console.log('Клик!');
// Блокирующий цикл:
const start = Date.now();
while (Date.now() - start < 3000) {}
console.log('Готово!');
// 3 секунды: кнопка не реагирует, анимации стоят
});Блокирующий код в обработчике событий «замораживает» интерфейс.
Частые ошибки
**Неправильно:** Думать, что JavaScript многопоточный
**Почему:** JavaScript — однопоточный (main thread). Браузер может выполнять JS-код только в одном потоке.
**Правильно:** JavaScript — один поток. Браузер использует Web Workers и APIs для параллельной работы.
**Неправильно:** Использовать циклы для ожидания
**Почему:** while (Date.now() < target) {} — блокирует весь поток.
**Правильно:** Используйте setTimeout, Promises или async/await для неблокирующего ожидания.
**Неправильно:** Путать setTimeout(fn, 0) с немедленным выполнением
**Почему:** setTimeout(fn, 0) планирует выполнение на следующий тик, а не выполняет немедленно.
**Правильно:** setTimeout(fn, 0) — «выполни, когда будет возможность», а не «прямо сейчас».
Важно запомнить
- JavaScript — однопоточный (main thread)
- Call stack — стек вызовов: функция вверх, завершение — вниз
- Синхронный код блокирует выполнение следующих строк
- Блокирующие операции «замораживают» интерфейс
- Асинхронные механизмы позволяют работать без блокировки
Связь
Назад: Вы знаете JavaScript Core и Intermediate (J0-JI19) — теперь вы понимаете, как выполнение устроено внутри.
Вперёд: Следующий урок (JA2) — callback-функции и setTimeout: первый асинхронный механизм.