Сердце (❤) JavaScript.

В этом посте мы узнаем о черном ящике, предоставляемом JavaScript для волшебного запуска нашего кода «Контекст выполнения».

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

Каждая строка этого запутанного кода, который вы до сих пор писали в своем любимом редакторе кода ( Vs code ❤ ), выполнялась внутри этого контекста выполнения, который мы сейчас обсудим.

Сядь поудобнее, расслабься и собери свою еду, потому что я сделаю все для тебя кристально ясным.

Тааак в javascript все происходит внутри контекста выполнения, то бишь все. Вы можете думать об этом как о среде, в которой код Js оценивается и выполняется.

Всякий раз, когда ваш браузер пересекается с каким-либо кодом JavaScript, механизм JavaScript браузера создает специальную среду для обработки преобразования и выполнения этого кода JavaScript. Эта среда известна как Execution Context.

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

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

Когда вы запускаете свой скрипт в браузере, механизм javascript создает другой тип контекста выполнения.

  • Глобальный контекст выполнения (GEC)

когда вы запускаете свой скрипт в первый раз или когда ваш код не находится внутри какой-либо функции, он помещается в глобальный контекст выполнения (GEC),

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

Примечание. Для каждого файла js существует только один GEC.

  • Контекст выполнения функции (FEC)

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

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

Как они создаются?

Теперь создание контекста выполнения происходит в два этапа:

  1. Этап создания
  2. Фаза выполнения

Этап создания

На этом этапе создается объект контекста выполнения (ECO), который содержит важную информацию/данные, которые наш код использует во время выполнения (этап выполнения).

Свойства устанавливаются и определяются внутри этого объекта (ECO) в три разных этапа.

  1. Создание переменного объекта (VO).
  2. Создание цепочки объемов.
  3. Придание значения ключевому слову this keyword.

Этап 1: создание объекта переменных

Объект переменной подобен контейнеру, который создается внутри контекста выполнения и хранит переменные и объявление функции в паре key : value (не в выражении функции).

В GEC к каждой переменной, объявленной с помощью var keyword, к этому объекту переменной добавляется свойство, которое указывает на переменную, и ее значение устанавливается в undefined,переменная, объявленная с помощью let или const, получает значение uninitialized, и когда дело доходит до объявления функции, свойство добавляется к объекту переменной, указывающему на эту функцию, все объявления функций будут храниться и станут доступными внутри ВО, даже до кода начинает работать.

В FEC этот переменный объект не создается, а конструируется похожий на массив объект с именем argument», который включает в себя все аргументы, предоставленные этой функции.

Такое хранение переменных и функций (объявлений) в памяти еще до выполнения кода называется поднятием.

Этап 2. Создание цепочки областей действия

В JavaScript область видимости — это способ узнать доступность фрагмента кода для других доменов вашего скрипта.

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

Теперь, когда функция (скажем, X()) определяется в другой функции (скажем, Y()), эта внутренняя функция X() будет иметь доступ к переменным, а другие функции, определенные во внешней функции Y(), также будут иметь доступ к коду внешней функции, но на этом все не останавливается, она также будет иметь доступ к коду своей прародительницы и так далее вплоть до GCE, такое поведение мы называем лексической областью видимости но обратное неверно.

Эта концепция области действия вызывает связанное явление в js, известное как замыкания, когда внутренняя функция получает доступ к коду, связанному с внешней функцией, даже после выполнения внешней функции. …умерла, ушла, давно ушла.

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

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

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

let a = 10;
function first() {
  let b = 20;
  second();
  function second() {
    let c = 30;
    console.log(a + b + c);
  }
}
first(); // output is 60

Здесь переменные a и b не определены в функции second(), она имеет доступ только к переменной c, которая определена в своей собственной области видимости (локальной области видимости), однако из-за лексической области видимости она имеет доступ к функции, в которой она находится, и функции его родитель. Итак, здесь, когда вы запускаете этот код, Js-движок не сможет найти ни переменную a, ни b, поэтому он пойдет вверх по цепочке контекста выполнения, чтобы сначала найти b и разрешить он успешно нашел его в области действия функции first(), после разрешения он продолжает поиск переменной a, для которой Js-движок проходит весь путь до глобального контекста выполнения и разрешает его.

Этот процесс, когда движок Js поднимается по цепочке различных контекстов выполнения или, можно сказать, проходит вверх по областям контекста (ов) выполнения для разрешения переменной или вызова/вызова функции, называется Цепочка областей.

Этап 3. Настройка значения ключевого слова this

В javascript ключевое слово this относится к области, которой принадлежит контекст выполнения.

В GEC this относится к глобальному объекту, который в случае браузера является объектом окна. Таким образом, в объявлении функции переменная, инициализированная ключевым словом «var», назначается этому глобальному объекту как методы и свойства соответственно.

so

var x = "hello"           
function y() {       
  console.log("hello")  
}

так же, как показано ниже

window.x = "hello"           
window.y = () => {       
  console.log("hello")  
}

Но в случае FEC он не создает ключевое слово «this», а имеет доступ к ключевому слову среды, в которой он определен.

Фаза выполнения

На этом этапе контекста выполнения начинается выполнение нашего кода, и после выполнения происходит извлечение из стека выполнения или стека вызовов, о чем мы расскажем позже в этом посте.

До сих пор объект Variable содержал переменные со значениями undefined и uninitialized в зависимости от того, объявлены ли переменные с ключевым словом var или с let/. const соответственно.

Здесь движок Js еще раз считывает код в EC, чтобы обновить эти переменные их фактическими значениями. Затем код анализируется, транспилируется и, наконец, выполняется.

Стек выполнения (стек вызовов)

Задумывались ли вы когда-нибудь, как движок JavaScript отслеживает создание и удаление различных EC, которые он создает во время выполнения скрипта? Ответ: Стек выполнения или просто Стек вызовов.

«JavaScript — это синхронный, однопоточный язык»

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

var name = "Victor";

function firstFunc() {
  var a = "Hi!";
  secondFunc();
  console.log(`${a} ${name}`);
}

function secondFunc(){
  var b = "Hey!";
  third();
  console.log(`${b} ${name}`);
}

function thirdFunc() {
  var c = "Hello!";
  console.log(`${c} ${name}`);
}

first();

Когда скрипт загружается в браузер, JS-движок браузера сначала создает специальную среду по умолчанию, которую мы подробно видели выше, которая является глобальным контекстом выполнения, и помещает ее в этот стек выполнения.

После этого при выполнении файла всякий раз, когда JS-движок находит вызов функции, он создает для него отдельный контекст выполнения функции, как показано на изображении ниже (шаг 2), и помещает его в стек поверх уже существующего GEC по умолчанию.

При выполнении firstFunc() он сталкивается с вызовом secondFunc() и приостанавливает выполнение firstFunc(), создает еще один FEC и помещает его в стек поверх FEC firstFunc(), затем снова создает отдельный FEC для ThirdFunc(). вызов.

EC сверху будет выполняться сначала движком JS, а после завершения выполнения он выталкивается из стека и начинается с выполнения EC ниже предыдущего активного EC, как показано на изображении выше, пока не достигнет GEC.

Заключение

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

Надеюсь, вы нашли эту статью полезной. Поделитесь им с друзьями и сетью.

Спасибо за прочтение.

мир ❤