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

Лексическое окружение - это ссылка на область внешних функций и часть контекста выполнения каждой функции.

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

Примеры закрытия в javascript

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

В этом примере вызывается mutiply и создается лексическая среда, в которой значение параметра mutiplyByTimes привязано к 3 и возвращается функция. трижды запоминает эту среду, поэтому, когда она вызывается путем передачи 5 в числовой параметр, она умножается.

Как замыкания можно использовать в javascript?

Частные методы с использованием замыканий

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

В приведенном выше примере у нас есть два частных метода: privateCounter и privateMethodToChangeValue, а также три открытых метода увеличения, уменьшения и getValue. Здесь два счетчика поддерживают свое собственное лексическое окружение, и мы можем видеть это на примере. counter1 приращение переменной не влияет на counter2 переменную. Таким образом, здесь мы не можем получить доступ к частным методам вне функции createCounter, но вместо этого мы можем получить доступ к открытым методам, которые возвращаются из функции createCounter.

Ориентированный на события

Здесь onClick создает закрытие и закрывает BACKGROUND_COLOR, который находится в глобальной области.

Еще примеры закрытия

Пример 1

В этом примере показана одна из проблем с замыканиями.

Здесь вывод 2 2, но мы ожидаем вывода как 1 и 2. Здесь два closures созданы циклом for, но каждый из них использует одну и ту же лексическую среду, потому что мы объявили i с var. Когда мы пытаемся выполнить console.log(i) в setTimeout, это будет последнее значение i, т.е. 2, потому что к этому времени цикл уже завершился. Мы можем исправить это, используя let

Мы использовали varkeyword вместо let, поэтому closure связывает переменную с областью видимости блока, что означает создание новых лексических сред для каждого цикла.

Пример 2

Еще один пример let. Closure содержит ссылку на исходные переменные. Кадр стека остается в памяти даже после выхода из внешней функции.

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

В приведенном выше примере мы пытаемся возвести число в квадрат. Итак, мы создали объект square.cache, в котором будем хранить как key value пару. В строке 2 мы проверяем объект кеша для этого конкретного ключа. Если его нет, мы вычислим его и сохраним в объекте square.cache. Если key существует, он не будет вычисляться, и все, что он уже хранится в кеше, он вернет.

Мы рассмотрим еще один пример для Фибоначчи с замыканием и мемоизацией:

В приведенном выше примере мы вычисляем Фибоначчи для ’n’. recursiveFib и fibonacci() находятся в той же области, а recursiveFib - это closure. Таким образом, cache может быть доступен во внутренней области.

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

В приведенном выше примере мы передаем add () в curry () на шаге 1.

На шаге 1 он возвращает эту функцию

При следующем вызове мы передадим еще один параметр curry(sum)(1), тогда результат будет

Затем, если мы передадим второй параметр curry(sum)(1)(2), мы получим окончательный результат.

использованная литература

Первоначально опубликовано на https://www.allaboutjavascriptworld.com 4 июля 2020 г.