В предыдущем посте мы говорили о контексте выполнения. Это был первый контекст выполнения, созданный на этапе компиляции.

Мы называем этот самый первый контекст выполнения глобальным контекстом выполнения (глобальным EC). Переменные, хранящиеся в соответствующей среде переменных, являются глобальными переменными.

Глобальный контекст выполнения отсутствует. При запуске скрипта можно создавать и удалять несколько контекстов выполнения.

Откуда берутся эти контексты выполнения?

Контекст выполнения всегда связан с этапом компиляции. Несколько контекстов выполнения подразумевают множество шагов компиляции.

Этот механизм связан с функциями.

Давайте рассмотрим пример с функцией.

Мы знаем, что консоль записывает «20» в конце выполнения, но что произошло в контексте выполнения?

Как всегда, он начинается с шага компиляции и создает глобальный контекст выполнения.

В среде переменных мы видим переменные `apple` и `appleTotal`, а также функцию `total`. Компиляция заканчивается и начинается выполнение.

Переменная `apple` обновляется до `10`, затем движок JavaScript считывает часть `total()`.

В этот момент повторяется тот же двухэтапный процесс. Шаг компиляции начинается снова, но на этот раз он касается только функции «total».

Механизм JavaScript создает новый контекст выполнения, «общий» контекст выполнения, и помещает его поверх глобального контекста выполнения.

Мы называем эту структуру стеком.

Стек имеет уникальную особенность: последний вошел, первый вышел. Это единственная функция, которая нас волнует в этом механизме.

Так же, как и глобальная, переменная среда существует в контексте выполнения «общий» с неопределенной переменной «цена».

Затем, в контексте «полного» выполнения, начинается этап выполнения. Переменная «цена» обновляется до «2».

Затем функция находит переменную `price` в контексте выполнения `total` и переменную `apple` в глобальном.

Хорошо, он находит обе переменные и возвращает результат вычисления.

В этот же момент возвращаемое значение присваивается переменной `appleTotal` в глобальном контексте выполнения.

В контексте «всего» выполнения не осталось исполняемых скриптов, поэтому движок JavaScript удаляет их из стека.

«Общий» контекст выполнения является последним, попадающим в стек, поэтому он первым покидает стек.

Теперь у нас есть последний в нижней части стека, глобальный контекст выполнения.

Единственный оставшийся исполняемый скрипт — это регистрация переменной `appleTotal` в консоли. После этого весь процесс завершен.

Из примера видно, как движок JavaScript управляет контекстами выполнения.

  • Движок JavaScript не компилирует код в функцию до тех пор, пока эта функция не будет вызвана.
  • Когда функция компилируется, создается новый контекст выполнения, который помещается на вершину стека.
  • Все контексты выполнения управляются в структуре стека. Процесс происходит от вершины стека к основанию.
  • Двухэтапный процесс компиляции и выполнения происходит всякий раз, когда вызывается функция.

В зависимости от того, как контексты выполнения располагаются друг над другом, мы называем это стеком вызовов.

Проверьте стек вызовов JavaScript в браузере

Современные браузеры упрощают проверку стека вызовов в инструментах разработки. Вот пример Хрома.

Для проверки стека вызовов нам нужно

  1. HTML-файл и
  2. точка останова

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

<script>
var apple = 10;
function total() {
 var price = 2;
 return apple * price;
}
var appleTotal = total();
console.log(appleTotal);
</script>

Запустите файл HTML в Chrome и откройте панель «Источники» в инструментах разработчика.

На панели «Источники» мы добавляем точку останова в функции «итого».

Затем обновите страницу, появится стек вызовов. «Общий» — это «общий» контекст выполнения, а «анонимный» — это глобальный контекст выполнения.

Какие выводы?

  • Несколько контекстов выполнения управляются в структуре стека. Это стек вызовов JavaScript.
  • Механизм JavaScript повторяет двухэтапный процесс компиляции и выполнения для добавления и удаления контекстов выполнения.
  • Новые контексты выполнения добавляются в начало, и верхний имеет приоритет для выполнения первым.
  • Существует только один глобальный контекст выполнения, и он всегда остается внизу стека вызовов. Он отображается как «анонимный» стек вызовов в инструментах разработки браузера.

Следующий…



использованная литература

  • Стоит отметить, что стек вызовов не является реальной структурой данных стека, определенной в мире внутреннего программирования. Браузер имитирует структуру данных стека, поэтому они не совсем одинаковы.
  • Если вам интересно узнать о структуре данных стека, этот ответ содержит интригующую аналогию.
  • Если вы используете Firefox, этот пост может помочь вам проверить стек вызовов.
  • У команды freeCodeCamp есть отличный пост о стеке вызовов с большим количеством примеров кода.