Мы сосредоточимся на понимании контекста выполнения и подъеме с примерами кода. Если вы новичок в JavaScript, понимание этих концепций поможет вам лучше понять ключевые слова this, scope и closure. Так что наслаждайтесь и продолжайте читать.

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

Лексическое окружение

Lexical environment – это структура данных, содержащая сопоставление идентификатор/переменная (идентификаторотносится к имени переменной, а переменнаяотносится к фактическому объект). Это относится как к функциям, так и к примитивным значениям.
Короче говоря, lexical environment — это место, где переменные и функции живут или физически присутствуют во время выполнения программы.

function greetUser() {
   var name="John"
   // Code block
}

В приведенном выше коде переменная name лексически находится внутри функции greetUser.

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

Обычно в коде у нас будет несколько lexical environments , не все среды запускаются один раз. Всякий раз, когда выполняется фрагмент кода, такой как вызов функции, доступ к переменной, это выполняется с помощью Execution Context.

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

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

Многое происходит за кулисами. Перед окончательным выполнением фрагмент кода проходит следующие этапы:

  • Токенизация: на этом этапе строка исходного кода разбивается на несколько осмысленных фрагментов, называемых токенами. Например, код var name = "John" разбивается на var, name и «John».
  • Парсинг: Следующий этап — парсинг, где массив токенов превращается в дерево вложенных элементов, понятных грамматике языка. Это дерево называется AST(Абстрактный синтаксис. Дерево).
  • Генерация кода: на этом этапе AST, созданный на этапе синтаксического анализа, превращается в исполняемый байт-код. Затем этот исполняемый байт-код дополнительно оптимизируется компилятором JIT (Just-In-Time).

Все эти вещи происходят в Execution Context. Таким образом, контекст выполнения — это среда, в которой выполняется фрагмент кода.

Существует два типа контекстов выполнения.

  • Глобальный контекст выполнения (GEC)
  • Локальный контекст выполнения (LEC) / Контекст выполнения функции (FEC)

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

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

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

Каждый контекст выполнения проходит две фазы: creation и execution.

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

GEC — это контекст выполнения, созданный для запуска основной части вашего кода; то есть любой код, который существует вне функции Javascript.

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

На этом этапе создаются две уникальные вещи:

  • Глобальный объект с именем window (для клиентского JS) и globalThis (для серверного JS).
  • Глобальная переменная с именем this, объект контекста выполнения, в котором в данном случае хранится ссылка на глобальный объект. В общем случае this хранит значение текущего контекста выполнения. В GEC this относится к объекту window.

Если в коде объявлены какие-либо переменные, память выделяется для переменной. Переменная инициализируется начальным значением, называемым undefined . Если в коде есть function, он помещается прямо в память. Для получения дополнительной информации об этом см. hoisting.

Этап выполнения

На этом этапе начинается выполнение кода. Здесь происходит присвоение значения переменной.

var name = "John";
function greetUser() {
console.log(this.name)
}

На этапе создания:

  • Создаются глобальные объекты window и this, которые совпадают.
  • Память выделяется для переменной name и функции greetUser.
  • Переменная name инициализируется специальным значением undefined. Функция greetUser помещается прямо в память.

На этапе исполнения.

  • Значение John присваивается переменной name.
  • Поскольку мы еще не вызвали функцию, она не будет выполнена. При каждом вызове функции создается новый контекст, который называется «локальный контекст или контекст выполнения функции».

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

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

var name = "John";

function greetUser() {
   console.log(this.name)
 }
//Invoke function
greetUser();

FEC проходит этапы создания и выполнения. Фаза выполнения функции имеет доступ к специальному значению, называемому arguments. Это аргументы, передаваемые функции. В нашем примере аргументы не передаются.

Обратите внимание, что объект window и переменная this, созданные в глобальном контексте выполнения, по-прежнему доступны в этом контексте.

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

Ссылки

https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth