Эта статья посвящена привязке переменных к областям действия. Итак, я предполагаю, что у вас есть базовое понимание программирования на любом языке. В противном случае это может показаться трудным для понимания. Потому что я собираюсь обсуждать немного туманные вещи. Начнем с определения привязки.

Что такое привязка?

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

Таким образом, привязка возникает всякий раз, когда мы объявляем и / или инициализируем переменную с использованием одного из этих ключевых слов: var, let и const в JavaScript. Например:

ES6 предлагает несколько лучших подходов для привязки блоков с использованием var, let и const. Но есть некоторые нечеткие вещи, которые движок JavaScript делает за кулисами. Сначала я бы использовал привязку var:

Привязка VAR: путаница

Здесь я трижды записываю переменную name в консоль в блоках if, else, и включающие. Разобьем блоки:

если заблокировать

Блокировать еще

заключающий блок

Теперь вы можете представить, что произойдет, если мы передадим в функцию логическое значение? Что ж, здесь происходит путаница. Если вы передадите true, функция получит результат из блоков if и включающих, в противном случае - из else и включающие блоки. Но помните, что name объявляется и инициализируется только в блоке if.

Как имя доступно в блоках else и включающие? Ответ - из-за подъема.

Подъем?

ES6 предлагает новую функцию под названием подъем. В общем, подъем - это механизм, который обрабатывает контексты выполнения в JavaScript. Это означает, что объявления переменных и функций (не инициализации) помещаются в память на этапах компиляции перед тем, как перейти к выполнению.

Объявления var обрабатываются так, как если бы они поднимались в верхнюю часть функции (включающий блок) или в глобальную область видимости, если они объявлены вне функции. Таким образом, движок JavaScript внутренне обрабатывает предыдущую функцию следующим образом:

Обратите внимание, что объявление поднято вверх, но инициализация остается именно там, где мы вводим переменную name. Это означает, что мы можем получить доступ к переменной name из любого места в охватывающем блоке в случае привязки var.

Чтобы решить эту проблему с помощью var, ES6 вводит объявления на уровне блоков с использованием let и const.

Объявления уровня блока

Если вы объявляете переменную в области видимости на уровне блока, используя любую из let и const, вы не сможете получить доступ к объявлению вне этой области видимости блока. Области блока могут быть созданы в следующих местах:

  • Внутри функции (функциональный блок)
  • Внутри блока (в двух фигурных скобках {})

Мы уже видели эти области видимости на уровне блока в приведенном выше примере. Теперь мы снова воспользуемся предыдущей функцией, но на этот раз с использованием let или const. В порядке. Я собираюсь использовать let. Рассмотрим следующий пример:

Обратите внимание на привязку let. На этот раз name существует только внутри блока if. Он недоступен за пределами блока if. Поскольку механизм JavaScript не поддерживает объявления let и const. Таким образом, имя недоступно в блоках else и включающих .

CONST Binding: недоразумение

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

Привязка const не позволяет вам изменять привязку, но не значение. Непонимание происходит, когда вы привязываете объект к идентификатору с помощью привязки const. Рассмотрим следующее:

Сначала мы привязываем литерал объекта к идентификатору person с типом привязки const. Это все еще верно. Но привязка const запрещает повторные объявления с теми же идентификаторами в той же области.

О, нет! Кажется, выше есть еще три идентификатора человека. Как?

Хорошо! Обратите внимание, что мы дважды привязываем новые имена к свойству name объекта person. Таким образом, это меняет то, что содержится в человеке, но не меняет того, к чему привязан этот человек. person содержит ссылку на литерал объекта. Таким образом, человек привязан к ссылке на этот объектный литерал. Таким образом, мы не меняем привязку идентификатора person, мы меняем значение свойства person.name.

Так что же происходит с последним фрагментом кода? Обратите внимание, что мы не только меняем здесь значение свойства name, но и снова назначаем новый литерал объекта идентификатору person, что неверно. Ранее это уже было объявлено и инициализировано с помощью привязки const. Это фактически нарушает правило привязки const и вызывает ошибку.

TDZ: временная мертвая зона

Временная мертвая зона или TDZ не упоминается в спецификации ECMAScript 6. Но обычно это используется, чтобы объяснить, почему привязки let и const недоступны до их объявления. Рассмотрим следующий пример:

Здесь оператор console.log (name) вызывает ошибку ссылки. Потому что мы обращаемся к переменной name перед ее объявлением. Место, где мы пытаемся получить доступ к переменной name, называется временной мертвой зоной. Это напоминает нам, что мы не можем получить доступ к переменным до их объявления для привязок let и const.

«Когда механизм JavaScript просматривает предстоящий блок и находит объявление переменной, он либо поднимает объявление в верхнюю часть функции или в глобальную область (для var), либо помещает объявление в TDZ (для let и const) ». - Николас Закас

Приведенный выше пример может выглядеть как следующий фрагмент кода, если вы сосредоточитесь на движке JavaScript.

Таким образом, любая попытка доступа к переменной в TDZ приводит к ошибке выполнения. Эта переменная удаляется из TDZ, когда выполнение переходит к объявлению переменной. То же самое происходит с привязкой const.

Почему именно ТДЗ?

Как и привязка блоков, TDZ предлагает поведение, которое с меньшей вероятностью приведет к непреднамеренным ошибкам. Переменные следует объявлять именно там, где они нужны. Вот почему ES6 порождает привязки let и const. Вам не разрешен доступ к их привязкам до их объявления.

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

Еще один ТДЗ!

До сих пор мы видели TDZ с использованием let и const. Но значение параметра по умолчанию в функции также имеет TDZ. Каждый параметр создает новую привязку, аналогичную объявлению let. И вы не можете ссылаться на эту привязку перед инициализацией. Инициализация параметра происходит, когда функция вызывается либо путем передачи для нее значения, либо с использованием значения по умолчанию. Посмотрите следующий код:

Когда мы вызываем функцию add, движок JavaScript присваивает параметрам следующие значения:

Здесь мы видим, что вызов add (undefined, 1) вызывает ошибку ссылки, сообщающую нам, что y не определен. Уведомление y было присвоено x перед его инициализацией. Но y в этот момент находится в TDZ. Следовательно, ссылки на y запрещены. Вот почему мы получаем ошибку.

Вот и все!

Вывод

Здесь я пытаюсь выделить три вещи. Один устанавливает привязку var, другой - объекты с помощью const, а третий - TDZ. Если вы хотите написать лучший код JavaScript, вы должны четко понимать эти, казалось бы, неясные три вещи.

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

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

Ссылки:

  1. "Переполнение стека"
  2. Изучение ES6
  3. Mozilla MDN
  4. Понимание ECMAScript 6