Tl; dr - я слышал о подъеме и о том, что движок Javascript перемещает код наверх. Я также слышал, что движок JavaScript работает поэтапно. Но не совсем круто сказать Я слышал это , поэтому я решил пройтись по Спецификации ECMAScript и найду несколько доказательств, чтобы я мог понять, как это работает на самом деле.

Введение🍿

Прежде всего, нет, «Подъем» на самом деле не существует в JavaScript. Подождите, что значит не существует ?! Вы все, наверное, слышали такой разговор: вы знаете, что такое «Подъем»? Да, это когда объявления переменных и функций физически перемещаются в начало вашего кода!

Что ж, я тоже это слышал, и я также слышал, что движок JavaScript работает поэтапно, и именно так происходит то, что объясняется как подъем. Но сказать Я слышал это… уже было недостаточно, поэтому я решил пройтись по » «Спецификации ECMAScript и наконец понять, что происходит.

Давай нырнем 🤓

Прежде всего, давайте рассмотрим пример «Подъем», чтобы убедиться, что мы все понимаем, о чем говорим.

console.log(myVariable) // undefined
var myVariable = 2

Это самый простой пример такого поведения, которое всегда объясняется как «подъем». Короче, что происходит на самом деле? Двигатель работает в две фазы (как минимум). Этап создания и Этап выполнения. Вот почему вы можете получить доступ к myVariable, прежде чем присвоить какое-либо значение. Обратите внимание, что вы можете получить к нему доступ, но он не определен. Хорошо, стоп! Давай подтвердим это.

Все началось, когда я нашел это упоминание в веб-документации MDN, в котором говорится, что подъема на самом деле не происходит (код не перемещается в начало).

Прочитав это, я решил погрузиться в ECMAScript Спецификацию и найти несколько доказательств. Что ж, я нашел этот раздел 10.4, который на самом деле говорит о шагах (фазах) для создания контекста выполнения.

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

Как правило, при входе в каждый контекст выполнения (перед выполнением кода) существует специальный объект для каждого выполнения - VariableEnvironment, который заполняется следующими свойствами: - (VE = VariableEnvironment)

1for параметр функции (формальные параметры) - установить свойство на VE с именем и значением параметра. Для параметров, которым не было присвоено значение - свойство VE с именем параметров будет создано со значением undefined.

2для объявления функции - установите свойство объекта VE с именем и значением функции - объект. Если VE уже содержит свойство с таким же именем, его значение и атрибуты заменяются.

3для объявления переменной (var) - установите свойство объекта VE с именем переменной и ее значение undefined. Если имя переменной совпадает с именем уже объявленного формального параметра или функции, объявление переменной не изменяет существующее свойство.

Пример

Мы можем снова взять предыдущий пример и объяснить шаг за шагом, основываясь на фазах, о которых мы говорили ранее.

1. console.log(myVariable) // undefined
2. var myVariable = 2
  1. Этап создания ( Создание экземпляра привязки объявления) :, как мы уже говорили ранее, для каждого выполнения ( глобальное выполнение или выполнение функции) механизм создает специальный объект VariableEnvironment,, который содержит все переменные и функции для этого выполнения. В строке 1 мы видим операцию выполнения, поэтому механизм переходит к строке 2 и видит объявление переменной, поэтому он связывает имя переменной myVariable с VariableEnvironment и устанавливает для него значение undefined после ECMAScript инструкция.
  2. Этап выполнения: на этом этапе механизм снова выполняет код, только на этот раз он выполняет его. В строке 1 мы видим операцию console.log (myVariable), поэтому механизм выполняет эту строку. Поскольку движок создал и заполнил VariableEnvironment перед , переменной myVariable ” существует. Вот почему мы можем получить доступ к этой переменной и записать ее, прежде чем присвоить какое-либо значение. В строке 2 механизм присваивает значение 2 параметру «myVariable, который определен в параметре VariableEnvironment .

Заключение

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

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

Если вас интересует Подъем в контексте Let и Const, вы можете прочитать эту статью: Расширенный JavaScript ES6 - временная мертвая зона, параметры по умолчанию И Let vs Var - Глубокое погружение!

Отправляйте отзывы, вопросы или запросы по темам. Я также был бы признателен 👏, если вам понравится этот пост, чтобы его могли найти и другие.

вы можете подписаться на меня в Twitter - Github - @ Lidor Avitan

Спасибо, и увидимся в следующий раз! 💛