Важно понимать, как работает внутренняя система, когда мы, как разработчик, что-то пишем. Это понимание того, как движок JS интерпретирует и запускает код, помогает разработчику писать более эффективный, оптимизированный и структурированный код.
Итак, сегодня позвольте мне поделиться своим пониманием того, что этот дракон называет «лексическим окружением» и «замыканием» в JavaScript.
Лексическое окружение
Всякий раз, когда JS-движок выполняет какую-либо функцию или, что более ценно, любой блок кода, он поддерживает некоторые данные внутри структурированным образом. Эта информация, поддерживаемая движком JS, известна как лексическая среда.
Лексическая среда в основном поддерживает 2 компонента:
- Запись среды: объект, в котором хранятся все локальные переменные и функции, объявленные в текущем блоке кода, как его свойства (а также значение
this
). - Ссылка на внешнее окружение:указатель на родительское лексическое окружение, связанное с внешним кодом.
Новое лексическое окружение создается каждый раз, когда выполняется блок функции/кода. Давайте разберемся на примере.
Выполнение вышеуказанной функции происходит, как показано ниже:
Родительская функция Лексическое окружение:
- Когда функция «Родитель» запускается, в начале вызова создается новое лексическое окружение.
- По мере выполнения функции запись среды будет содержать информацию о локальной переменной и функции, поэтому в нашем примере, когда будет выполняться родительская функция, ее запись среды будет иметь функции «greet» и «child» в качестве свойств.
- Второй компонент лексического окружения (ссылка на внешнее окружение) здесь указывает на глобальноелексическое окружение, которое связано со всем сценарием.
- наша функция возвращает «дочернюю» функцию в качестве возвращаемого значения.
Дочерняя функция Лексическое окружение:
- При выполнении «дочерней» функции снова создается новое лексическое окружение. (назовем это внутренней лексической средой)
- Запись среды дочерней функции будет иметь «имя» в качестве свойств (это локальная переменная).
- Лексическое окружение дочерней функции будет иметь ссылку на лексическое окружение «родительской» функции (второй компонент лексического окружения, назовем его внешним лексическим окружением)
- Поэтому, когда выполняется дочерняя функция, даже если переменная «greet» не определена в дочерней функции, а родительская функция уже выполнена, пользователь все равно увидит «Hello World!!!». в журнале, потому что когда код хочет получить доступ к переменной — сначала просматривается внутреннее лексическое окружение, затем внешнее, затем более внешнее и так далее до глобального.
Обратите внимание: лексическая среда существует теоретически в спецификации языка для описания того, как все работает. Мы не можем получить этот объект в нашем коде и манипулировать им напрямую.
Закрытие
Замыкание — это комбинация функции, связанной вместе (вложенной) со ссылками на ее окружающее состояние (лексическое окружение).
Проще говоря, Closure — это функция, которая запоминает свою внешнюю область видимости (внешнее лексическое окружение) и может получить к ней доступ. Замыкание дает вам доступ к области действия внешней функции из внутренней функции. Каждая функция в JavaScript может быть определена как замыкание.
Преимущества закрытия:
- Сохранение состояния: здесь будет сохранено состояние переменной из-за закрытия.
- Инкапсуляция: мы можем создавать частные методы и переменные, используя замыкание.
- Частичные функции: мы можем создавать частичные функции с помощью замыкания.
В основном закрытие помогает и облегчает нашу работу везде, от вложенных функций до обработки событий и асинхронного программирования. Все программисты JavaScript полагались на эту функцию (просто мы этого не осознаем :D).