Чтобы глубоко понять язык JavaScript, очень важно знать его внутреннюю рабочую структуру. Контекст выполнения и стек вызовов являются одними из них.

Что такое контекст выполнения?

Проще говоря, контекст выполнения — это среда, в которой выполняется фрагмент кода JavaScript. Хранит всю необходимую информацию для выполнения кода, например, переменные среды, цепочку областей видимости и ключевое слово this.

Контекст выполнения имеет два типа — один является глобальным контекстом выполнения, а второй — контекстом выполнения функции.

Глобальный контекст выполнения. Это контекст по умолчанию, созданный для кода, который не находится внутри какой-либо функции (код верхнего уровня). Так что в основном он представляет только один в стеке вызовов.

Контекст выполнения функции. Это контекст, созданный для каждого вызова функции. Это означает, что при каждом отдельном вызове функции создается новый контекст выполнения для этой функции в стеке вызовов.

Давайте разберемся как в контексте с примером фрагмента кода:

В приведенном выше фрагменте кода контекст Global Execution делает записи всех глобальных переменных и кода функции. И контекст выполнения отдельной функции делает записи соответствующих переменных и аргументов.

Примечание. Функция стрелки не имеет аргументов и этой функции ключевого слова.

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

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

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

Теперь в нашем коде мы сначала вызвали основную функцию. Поэтому его контекст выполнения будет создан и добавлен в стек вызовов поверх глобального контекста.

let calculate = main(100, 70 )
// Calling the function name - main

Теперь, если мы проверим нашу основную функцию, в третьей строке мы вызываем функцию вычитания. Это означает, что пришло время для создания контекста выполнения функции вычитания и размещения его в стеке вызовов поверх основной функции. Здесь основная функция будет приостановлена ​​и будет ждать возврата из функции вычитания.

function main(a, b) {
  let sum = a + b;
  let subs = subtract(a, b); // Calling subtract function
  return sum + subs;
}

Мы можем видеть в нашей функции вычитания, что мы просто возвращаем значение, вычитая переданные параметры. Никакая другая функция больше не вызывается. Таким образом, мы можем легко вернуть значение, закрыть функцию вычитания и извлечь контекст ее выполнения из стека вызовов. И вернуться к основной функции.

function substract(a, b){
  return a - b;
}

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

Наконец, мы вернули значение из основной функции и сохранили его в глобальной переменной «Рассчитать». Здесь стек вызовов станет пустым и будет ждать любого будущего вызова функции, пока программа не завершится или браузер не закроется.

Здесь мы увидели, как после компиляции кода создается глобальный контекст выполнения, и как каждый вызов отдельной функции создает контекст выполнения для себя, и как стек вызовов использует эти контексты выполнения для отслеживания потока кода и выполнения.

Подробнее о цепочке Scope — https://medium.com/@jay.developer12/javascript-scope-chain-ceda8c81642a

Удачного кодирования 🙂🙂🙂🙂