Введение

Одна из самых важных концепций в Javascript для понимания — замыкания. Это связано с тем, что понимание того, как работают замыкания, позволяет нам писать более качественные и эффективные программы. Также очень часто задают вопросы о замыканиях во время собеседований по интерфейсу и Javascript.

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

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

Чтобы понять замыкания, нам сначала нужно понять, что такое лексическая среда, потому что она формирует базовый механизм работы замыканий.

Лексическая среда — это структура данных, которая содержит сопоставление переменных в области видимости. Он создается во время создания функции и также называется записью среды. Он содержит два компонента:

  1. Запись среды: структура данных, содержащая карту переменных и их текущих значений в функции.
  2. Ссылка на лексическое окружение непосредственной внешней области видимости (родительская функция или глобальная).

Поняв вышеизложенное, давайте перейдем к определению того, что такое замыкание.

Что такое закрытие

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

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

Как работают замыкания:

Теоретическое понимание того, как замыкания работают, может немного сбивать с толку, поэтому давайте взглянем на приведенный ниже пример кода, чтобы объяснить, как это работает.

Мы рассмотрим выполнение кода и объяснения по шагам.

После разбора скрипта движок javascript начнет выполнять код построчно. Первая операция заключается в запуске функции makeCounter() и присвоении возвращенного элемента counter.

При выполнении вызова makeCounter() механизм создаст замыкание для хранения переменных и ссылок для внутренних функций.

В этот момент значение count равно 0, и возвращается ссылка на increaseCounter(). Возвращаемая ссылка назначается счетчику.

Замыкание для функции makeCounter() по-прежнему доступно в памяти, хотя функция makeCounter() уже завершила выполнение. Это связано с тем, что на замыкание по-прежнему ссылается переменная счетчика. Движок будет поддерживать замыкание, чтобы иметь доступ к переменной count при выполнении функции counter().

Во второй строке выполняется вызов функции counter(). В этом вызове движок получает переменную count из внешней области видимости, увеличивает ее на 1 и возвращает обновленное значение. Он может сделать это, даже если в нем не определен count, потому что его закрытие имеет ссылку на внешнюю область видимости.

Замыкания разрешают переменные в следующем порядке:

  1. Переменные, объявленные в своей области видимости
  2. Переменные, объявленные в области видимости внешней функции
  3. Переменные, объявленные в глобальной области видимости

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

На данный момент значение count равно 1.

Следующая строка кода снова запускает вызов функции counter(). Выполняет то же действие, что и предыдущая операция. В конце скрипта значение count равно 2.

Примеры использования Closures в реальном мире

Давайте взглянем на некоторые примеры использования замыканий в реальном мире.

Частные переменные

Мы можем создавать приватные переменные, которые можно безопасно обновлять, как в приведенном выше коде. Функция driveCar() возвращает только методы для получения или обновления значения скорости, но не саму скорость. Таким образом, никакая часть нашего кода не может установить скорость на › 70, потому что у нас есть защита от этого.

Кэширование

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

Декораторы

Мы можем использовать замыкания при написании некоторых функций-декораторов. Декораторы — это функции, которые принимают и возвращают модифицированную версию функции. Вместо использования IIFE для создания решения для кэширования, описанного выше, мы можем создать декоратор кэша, который позволит нам добавить кэширование к любой функции. Давайте посмотрим код для этого ниже.

Заключение

Мы рассмотрели, что такое замыкания, почему они важны и как использовать их преимущества в Javascript. Мы также рассмотрели некоторые примеры использования замыканий в реальном мире.

Обладая этими знаниями, мы теперь можем писать более качественный и эффективный код javascript. Мы также можем воспользоваться тем фактом, что javascript является функциональным языком программирования, и использовать замыкания для написания более функционального кода.

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