Чтобы глубоко понять язык 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
Удачного кодирования 🙂🙂🙂🙂