0Pricing
JavaScript Academy · Урок

Стек вызовов

Посмотрите, как отслеживаются вызовы функций.

«Стек вызовов» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.

Что такое стек вызовов

Стек вызовов — это механизм, с помощью которого JavaScript отслеживает, какая функция выполняется сейчас и куда нужно вернуть управление. Каждый вызов функции помещается наверх стека, а после завершения снимается.

Это структура LIFO: последним вошёл — первым вышел.

Помещение и снятие со стека

При вызове функции в стек помещается кадр. При возврате кадр снимается. Следите за порядком записей журнала при вложенных вызовах.

function first() {
  console.log('first start');
  second();
  console.log('first end');
}

function second() {
  console.log('second');
}

first();

LIFO в действии

Функция, вызванная последней, должна завершиться, прежде чем возобновится выполнение функции под ней. Внутренний вызов завершается первым, хотя начался последним.

function a() {
  console.log('enter a');
  b();
  console.log('exit a');
}
function b() {
  console.log('enter b');
  c();
  console.log('exit b');
}
function c() {
  console.log('c runs');
}
a();

Синхронное выполнение блокирует

JavaScript выполняет только одно действие за раз в одном потоке. Пока стек содержит кадры, ничто другое не выполняется. Синхронный код блокирует выполнение до завершения.

console.log('start');

function busy() {
  let sum = 0;
  for (let i = 0; i < 1000; i++) sum += i;
  return sum;
}

console.log(busy());
console.log('end');

Возвращаемые значения идут вниз

Когда каждый кадр снимается, его возвращаемое значение передаётся ожидающему вызывающему коду, расположенному ниже в стеке.

function square(n) {
  return n * n;
}
function sumOfSquares(a, b) {
  return square(a) + square(b);
}

console.log(sumOfSquares(3, 4));

Рекурсия увеличивает стек

Каждый рекурсивный вызов добавляет ещё один кадр. Стек растёт, пока не будет достигнут базовый случай, после чего разматывается кадр за кадром.

function countdown(n) {
  if (n === 0) {
    console.log('liftoff');
    return;
  }
  console.log(n);
  countdown(n - 1);
}

countdown(3);

Переполнение стека

Размер стека ограничен. Рекурсия без базового случая продолжает добавлять кадры, пока движок не выдаст RangeError: превышен максимальный размер стека вызовов.

function endless(n) {
  return endless(n + 1);
}

try {
  endless(1);
} catch (e) {
  console.log(e.name);
}

Порядок выполнения предсказуем

Поскольку стек работает строго по принципу LIFO, а код выполняется синхронно, порядок синхронных записей журнала всегда предсказуем. Его можно проследить вручную.

function outer() {
  console.log(1);
  inner();
  console.log(3);
}
function inner() {
  console.log(2);
}
outer();
console.log(4);

Где появляется асинхронность

Стек вызовов выполняет только синхронный код. Функции вроде setTimeout передают работу среде выполнения, которая позже помещает обратные вызовы в очереди. Эти обратные вызовы выполняются только после того, как стек станет пустым.

Так мы подходим к циклу событий.

console.log('A');
setTimeout(() => console.log('B (later)'), 0);
console.log('C');

Сначала стек должен очиститься

Даже таймер с нулевой задержкой ждёт завершения всего синхронного кода. Обратный вызов не может выполниться, пока в стеке остаются кадры.

console.log('sync 1');
setTimeout(() => console.log('timeout'), 0);
console.log('sync 2');
console.log('sync 3');

Зачем нужен стек вызовов

Понимание стека вызовов объясняет, почему длинные синхронные циклы заставляют страницу зависать, почему рекурсия может привести к переполнению и почему асинхронные обратные вызовы всегда выполняются последними. Это основа всего, что происходит в цикле событий.

function compute() {
  return [1, 2, 3].reduce((a, b) => a + b, 0);
}
console.log('before');
console.log(compute());
console.log('after');

Быстрая проверка

Какому принципу упорядочивания подчиняется стек вызовов?

Повторение: стек вызовов

Вы изучили основу выполнения в движке:

  • Стек вызовов отслеживает выполняющиеся функции в порядке LIFO.
  • JavaScript однопоточен, а синхронный код блокирует выполнение.
  • Рекурсия увеличивает стек и может привести к его переполнению.
  • Асинхронные обратные вызовы ждут, пока стек освободится, что приводит нас к циклу событий.

Часто задаваемые вопросы

Урок «Стек вызовов» бесплатный?

Да — полный текст урока «Стек вызовов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Стек вызовов»?

Посмотрите, как отслеживаются вызовы функций. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать JavaScript Academy?

Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Стек вызовов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке JavaScript Academy?

Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Стек вызовов
  2. Макрозадачи и очередь задач
  3. Микрозадачи и промисы
  4. queueMicrotask и порядок выполнения
← Назад к JavaScript Academy