Это концепция реализации привязки лексической области видимости в javascript с помощью функций. Closure
создается, когда внутренние функции могут обращаться к переменным внешней функции. Замыкание запоминает состояние функции даже после того, как функция была возвращена. Если нам нужно создать closure
, мы должны определить функцию внутри другой функции и вернуть ее, чтобы эта внутренняя функция имела доступ к внешним переменным функции.
Лексическое окружение - это ссылка на область внешних функций и часть контекста выполнения каждой функции.
В отличие от обычной функции, closure
позволяет функции получить доступ к сохраненным переменным через закрывающую копию их ссылок, даже если она вызывается вне функции. Поскольку каждая функция будет иметь ссылку на свое лексическое окружение, которое она видит и может получить доступ к переменным, объявленным вне функции.
Примеры закрытия в javascript
Здесь createClosure
- это экземпляр функции innerFunction, и он создается при вызове outerFunction. innerFunction поддерживает ссылку на свою лексическую среду, поэтому в среду входят любые переменные, которые были в области видимости во время создания закрытия, поэтому существует переменная externalVariable. Пример:
В этом примере вызывается mutiply
и создается лексическая среда, в которой значение параметра mutiplyByTimes
привязано к 3 и возвращается функция. трижды запоминает эту среду, поэтому, когда она вызывается путем передачи 5 в числовой параметр, она умножается.
Как замыкания можно использовать в javascript?
Частные методы с использованием замыканий
JavaScript не предоставляет способа сделать частным, как любые другие языки программирования, и это можно сделать с помощью замыканий. Здесь частные методы, полезные для ограничения доступа и управления глобальными пространствами имен. В объектно-ориентированном программировании это похоже на сокрытие и инкапсуляцию данных, и это достигается с помощью closures
. Давайте посмотрим на пример
В приведенном выше примере у нас есть два частных метода: privateCounter
и privateMethodToChangeValue
, а также три открытых метода увеличения, уменьшения и getValue. Здесь два счетчика поддерживают свое собственное лексическое окружение, и мы можем видеть это на примере. counter
1 приращение переменной не влияет на counter2
переменную. Таким образом, здесь мы не можем получить доступ к частным методам вне функции createCounter
, но вместо этого мы можем получить доступ к открытым методам, которые возвращаются из функции createCounter
.
Ориентированный на события
Здесь onClick создает закрытие и закрывает BACKGROUND_COLOR, который находится в глобальной области.
Еще примеры закрытия
Пример 1
В этом примере показана одна из проблем с замыканиями.
Здесь вывод 2 2
, но мы ожидаем вывода как 1 и 2. Здесь два closures
созданы циклом for, но каждый из них использует одну и ту же лексическую среду, потому что мы объявили i
с var
. Когда мы пытаемся выполнить console.log(i)
в setTimeout
, это будет последнее значение i, т.е. 2, потому что к этому времени цикл уже завершился. Мы можем исправить это, используя let
Мы использовали var
keyword вместо 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 г.