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

В этом посте я собираюсь исследовать процесс того, как движок JavaScript читает и выполняет ваш код.

Терминология:

Контекст выполнения: создается при вызове функции. Сам контекст выполнения можно рассматривать как объект JS, который отвечает за отслеживание следующей информации о вызванной функции: что вызвало функцию (this); каковы его аргументы, переменные и функции; и к каким аргументам, переменным и функциям он имеет доступ, что находится вне его (области действия).

Глобальный контекст выполнения: создается, когда мы вызываем наш исходный код.

Стек вызовов выполнения: стек отвечает за отслеживание контекста выполнения. Глобальный контекст выполнения всегда находится внизу. Каждый новый контекст выполнения добавляется в начало. Добавление каждого нового контекста выполнения в стек приводит к тому, что механизм JS приостанавливает выполнение в текущем контексте, перемещается во вновь добавленный контекст и запускает процесс выполнения; после завершения JS-движок возвращается к своему предыдущему контексту и возобновляет работу с того места, где он оставался.

Цепочка областей видимости: список аргументов, переменных и функций, доступных для вызываемой функции из внешней среды.

VariableObject: можно рассматривать как объект, который отслеживает аргументы, функции и переменные вызываемой функции. Все аргументы, функции и переменные являются свойствами VariableObject.

Это: связано с объектом, который вызвал функцию.

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

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

После добавления контекста в стек движок JS выполняет следующие два основных шага:

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

  • Создайте цепочку областей видимости
  • Создайте объект VariableObject
    a. Определите аргументы и присвойте им имена как свойства VariableObject, и значения аргументов станут значением свойств.
    b. Просканируйте и определите объявление функции и назначьте их как свойства VariableObject и сделайте ссылку на свойство в объявлении функции
    c. Просканируйте и определите любые переменные (включая функциональные выражения). Если имя переменной совпадает с именем ранее определенного свойства, пропустите переменную полностью и перейдите к следующей переменной. Если переменная не существует, сделайте ее свойством VariableObject и присвойте ей значение undefined (также проверьте, как let и const оцениваются движком JS ) *.
  • Определите ценность этого

Этап активации / выполнения:

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

Мы применим следующие шаги к нашему глобальному контексту выполнения:

Переход к стадии создания (глобальный контекст выполнения):

  • Создайте цепочку областей видимости
  • Создать VariableObject
  • this: глобальный

Войдите в стадию активации / выполнения (глобальный контекст выполнения):

Начните выполнение кода сверху вниз.

  • В первой строке мы встречаем переменную addNum, для которой VariableObject определено как «undefined». Передаем ему ссылку на функцию суммы. Теперь наш VariableObject для глобального контекста выполнения готов,
  • Во второй строке мы встречаем объявление функции, которое обрабатывается на этапе создания. Мы можем пропустить это и перейти к следующей строке
  • Третья строка, функция addNum вызывается путем передачи аргументов 2 и 3. Согласно нашему определению содержимого выполнения, новый контекст выполнения создается после вызова функции. И контекст добавлен в наш стек выполнения. Теперь мы переходим к выполнению функции, следуя тем же шагам, что и для глобального контекста выполнения.

Этап создания (контекст выполнения функции addNum):

  • Создайте цепочку областей видимости
  • Создать VariableObject
  • this: global // причина, по которой this равно global, в том, что глобальная среда отвечает за вызов функции. И это связано с объектом, который вызвал функцию.

Этап активации / выполнения (контекст выполнения функции addNum):

И снова мы начинаем сверху и продвигаемся вниз.

  • В первой строке мы встречаем console.log, который представляет собой выражение, которое оценивает значение 5 для консоли.
  • Завершите выполнение функции, удалите контекст из стека и вернитесь в глобальный контекст выполнения с того места, где мы остановились.

И мы повторяем описанный выше шаг для вызова функции minusNum.

Завершение выполнения minusNum приведет нас к завершению нашего глобального контекста выполнения, поскольку больше нет операторов.
И глобальный контекст выполнения выталкивается из стека выполнения, и программа завершается.

Наконец, я оставлю вам фрагмент кода, чтобы проверить ваше понимание концепции. Свое объяснение вы можете отправить в комментариях.

Подробнее:

Обновления: