Я изо всех сил стараюсь обернуть голову вокруг замыканий JavaScript.
Я получаю это, возвращая внутреннюю функцию, она будет иметь доступ к любой переменной, определенной в ее непосредственном родителе.
Где это будет полезно для меня? Возможно, я еще не совсем обдумал это. Большинство примеров, которые я видел в Интернете , не дают никакого реального кода, только расплывчатые примеры.
Может кто-нибудь показать мне реальное использование замыкания?
Это, например, один?
var warnUser = function (msg) {
var calledCount = 0;
return function() {
calledCount++;
alert(msg + '\nYou have been warned ' + calledCount + ' times.');
};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Ответы:
Я использовал замыкания для таких вещей, как:
Как вы можете видеть,
a
теперь это объект с методомpublicfunction
(a.publicfunction()
), который вызываетprivatefunction
, который существует только внутри замыкания. Вы НЕ можете звонитьprivatefunction
напрямую (т.е.a.privatefunction()
), простоpublicfunction()
.Это минимальный пример, но, может быть, вы можете увидеть его применение? Мы использовали это для применения публичных / частных методов.
источник
Предположим, вы хотите посчитать, сколько раз пользователь нажимал кнопку на веб-странице.
Для этого вы запускаете функцию по
onclick
событию кнопки, чтобы обновить счетчик переменнойТеперь может быть много подходов, таких как:
1) Вы можете использовать глобальную переменную и функцию для увеличения счетчика :
Но подводный камень в том, что любой скрипт на странице может изменить счетчик без вызова
updateClickCount()
.2) Теперь вы можете подумать об объявлении переменной внутри функции:
Но эй! Каждый раз, когда
updateClickCount()
вызывается функция, счетчик снова устанавливается на 1.3) Думаете о вложенных функциях ?
Вложенные функции имеют доступ к области «над» ними.
В этом примере внутренняя функция
updateClickCount()
имеет доступ к переменной счетчика в родительской функцииcountWrapper()
Это могло бы решить дилемму противодействия, если бы вы могли добраться до
updateClickCount()
функции извне, и вам также нужно найти способ выполнитьcounter = 0
только один раз, а не каждый раз.4) Закрытие на помощь! (функция, вызывающая себя) :
Самопризывающая функция запускается только один раз. Он устанавливает
counter
ноль (0) и возвращает выражение функции.Этот путь
updateClickCount
становится функцией. «Замечательная» часть заключается в том, что он может получить доступ к счетчику в родительской области видимости.Это называется закрытием JavaScript . Это позволяет функции иметь « частные » переменные.
Он
counter
защищен областью действия анонимной функции и может быть изменен только с помощью функции добавления!Более живой пример на Закрытие:
Ссылка: https://www.w3schools.com/js/js_function_closures.asp
источник
Пример, который вы приводите, превосходен. Замыкания - это механизм абстракции, который позволяет очень аккуратно разделять задачи. Ваш пример - это случай отделения инструментария (подсчета вызовов) от семантики (API сообщения об ошибках). Другое использование включает в себя:
Передача параметризованного поведения в алгоритм (классическое программирование высшего порядка):
Имитация объектно-ориентированного программирования:
Реализация экзотического управления потоком, такого как обработка событий jQuery и AJAX API.
источник
int
?) В последний раз, когда я проверял, JavaScript был языком типа «утка». Возможно, вы думали о Java?Я знаю, что очень поздно отвечаю на этот вопрос, но это может помочь любому, кто все еще ищет ответ в 2018 году.
Javascript замыкания могут использоваться для реализации функций дросселя и отладки в вашем приложении.
Дросселирование :
Регулирование налагает ограничение на максимальное количество вызовов функции в течение определенного времени. Как в «выполнять эту функцию не чаще, чем раз в 100 миллисекунд».
Код:
Debouncing :
Дебусинг накладывает ограничение на функцию, которая не будет вызываться снова, пока не пройдет определенное количество времени без ее вызова. Как в «выполнить эту функцию, только если прошло 100 миллисекунд без ее вызова».
Код:
Как вы можете видеть, замыкания помогли реализовать две прекрасные функции, которые должны быть у каждого веб-приложения для обеспечения функциональности интерфейса.
Надеюсь, это кому-нибудь поможет.
источник
Да, это хороший пример полезного закрытия. Вызов warnUser создает
calledCount
переменную в своей области и возвращает анонимную функцию, которая хранится вwarnForTamper
переменной. Поскольку по-прежнему есть замыкание, использующее переменную namedCount, оно не удаляется при выходе из функции, поэтому каждый вызов функцииwarnForTamper()
будет увеличивать переменную области действия и сообщать о значении.Наиболее распространенная проблема, которую я вижу в StackOverflow, - это когда кто-то хочет «задержать» использование переменной, которая увеличивается в каждом цикле, но, поскольку переменная ограничена областью действия, каждая ссылка на переменную будет после окончания цикла, что приведет к конечное состояние переменной:
Это приведет к тому, что в каждом предупреждении будет отображаться одно и то же значение
i
, значение которого было увеличено до завершения цикла. Решением является создание нового замыкания, отдельной области видимости для переменной. Это можно сделать с помощью мгновенно выполняемой анонимной функции, которая получает переменную и сохраняет ее состояние в качестве аргумента:источник
В частности, в языке JavaScript (или любом языке ECMAScript) замыкания полезны для сокрытия реализации функциональных возможностей, в то же время раскрывая интерфейс.
Например, представьте, что вы пишете класс служебных методов даты и хотите, чтобы пользователи могли искать названия дней недели по индексу, но вы не хотите, чтобы они могли изменять массив имен, который вы используете внутри.
Обратите внимание, что
days
массив может быть просто сохранен как свойствоdateUtil
объекта, но тогда он будет виден пользователям скрипта, и они могут даже изменить его, если захотят, даже не нуждаясь в исходном коде. Однако, поскольку он заключен в анонимную функцию, которая возвращает функцию поиска по дате, он доступен только для функции поиска, поэтому теперь он защищен от несанкционированного доступа.источник
Существует раздел на практических Closures в Mozilla Developer Network .
источник
return function ()...
код, но он все еще работает нормально. Затвор не nessecaryДругое распространенное использование для замыканий - это привязка
this
метода к определенному объекту, что позволяет вызывать его в другом месте (например, в качестве обработчика событий).Всякий раз, когда происходит событие перемещения мыши,
watcher.follow(evt)
вызывается.Замыкания также являются неотъемлемой частью функций более высокого порядка, позволяя использовать очень распространенный шаблон переписывания нескольких похожих функций в качестве одной функции более высокого порядка путем параметризации разнородных частей. В качестве абстрактного примера,
становится
где A и B - не синтаксические единицы, а строки исходного кода (не строковые литералы).
См. « Оптимизация моего JavaScript с помощью функции » для конкретного примера.
источник
Здесь у меня есть приветствие, которое я хочу сказать несколько раз. Если я создаю замыкание, я могу просто вызвать эту функцию, чтобы записать приветствие. Если я не создаю замыкание, я должен каждый раз передавать свое имя.
Без закрытия ( https://jsfiddle.net/lukeschlangen/pw61qrow/3/ ):
С закрытием ( https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/ ):
источник
Если вы знакомы с концепцией создания экземпляра класса в объектно-ориентированном смысле (т.е. для создания объекта этого класса), то вы близки к пониманию замыканий.
Подумайте об этом так: когда вы создаете два экземпляра объекта Person, вы знаете, что переменная-член класса «Name» не используется совместно экземплярами; каждый объект имеет свою собственную «копию». Точно так же, когда вы создаете замыкание, свободная переменная ('namedCount' в вашем примере выше) привязывается к 'экземпляру' функции.
Я думаю, что ваш концептуальный скачок слегка затруднен тем фактом, что каждая функция / замыкание, возвращаемое функцией warnUser (кроме: это функция более высокого порядка ), связывает 'namedCount' с тем же начальным значением (0), тогда как часто при создании замыканий более полезно передавать различные инициализаторы в функцию более высокого порядка, подобно передаче различных значений в конструктор класса.
Итак, предположим, что когда 'selectedCount' достигает определенного значения, вы хотите завершить сеанс пользователя; для этого могут потребоваться разные значения в зависимости от того, поступает ли запрос из локальной сети или из-за плохого интернета (да, это надуманный пример). Чтобы достичь этого, вы можете передать различные начальные значения для namedCount в warnUser (то есть -3 или 0?).
Часть проблемы с литературой - номенклатура, используемая для их описания («лексическая область», «свободные переменные»). Не позволяйте этому обмануть вас, замыкания проще, чем кажется ... prima facie ;-)
источник
Здесь у меня есть один простой пример концепции закрытия, которую мы можем использовать на нашем сайте электронной коммерции или во многих других. Я добавляю ссылку jsfiddle с примером. он содержит небольшой список товаров из 3 предметов и один счетчик корзины.
Jsfiddle
источник
Использование замыканий:
Замыкания являются одной из самых мощных функций JavaScript. JavaScript допускает вложение функций и предоставляет внутренней функции полный доступ ко всем переменным и функциям, определенным внутри внешней функции (и ко всем другим переменным и функциям, к которым внешняя функция имеет доступ). Однако внешняя функция не имеет доступа к переменным и функциям, определенным внутри внутренней функции. Это обеспечивает своего рода безопасность для переменных внутренней функции. Кроме того, поскольку внутренняя функция имеет доступ к области видимости внешней функции, переменные и функции, определенные во внешней функции, будут жить дольше, чем сама внешняя функция, если внутренней функции удастся выжить после срока службы внешней функции.
Пример :
В приведенном выше коде переменная name внешней функции доступна для внутренних функций, и нет другого способа получить доступ к внутренним переменным, кроме как через внутренние функции. Внутренние переменные внутренней функции действуют как безопасные хранилища для внутренних функций. Они содержат «постоянные», но защищенные данные для внутренних функций, с которыми можно работать. Функции даже не нужно присваивать переменной или иметь имя. читай здесь для деталей
источник
Мне нравится пример фабрики функций Mozilla .
источник
Шаблон модуля JavaScript использует замыкания. Его симпатичный шаблон позволяет вам иметь что-то похожее на «публичные» и «приватные» переменные.
источник
Недавно я написал статью о том, как можно использовать замыкания для упрощения кода обработки событий. Он сравнивает обработку событий ASP.NET с клиентским jQuery.
http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/
источник
Эта тема очень помогла мне лучше понять, как работают замыкания. С тех пор я провел несколько собственных экспериментов и придумал этот довольно простой код, который может помочь другим людям понять, как замыкания могут быть использованы на практике и как использовать замыкания на разных уровнях для поддержания переменных, подобных статическим и / или глобальные переменные без риска их перезаписи или путаницы с глобальными переменными. Это отслеживает нажатия кнопок, как на локальном уровне для каждой отдельной кнопки, так и на глобальном уровне, считая каждый щелчок кнопки, внося вклад в единое число. Примечание. Для этого я не использовал глобальные переменные, что является своего рода смыслом упражнения - иметь обработчик, который можно применить к любой кнопке, которая также вносит вклад в глобальные изменения.
Пожалуйста, эксперты, дайте мне знать, если я совершил какие-либо плохие практики здесь! Я все еще изучаю этот материал сам.
источник
Справка: Практическое использование крышек
На практике замыкания могут создавать элегантные конструкции, позволяющие настраивать различные вычисления, отложенные вызовы, обратные вызовы, создавать инкапсулированную область видимости и т. Д.
Пример метода сортировки массивов, который принимает в качестве аргумента функцию условия сортировки:
Отображение функционалов в качестве метода отображения массивов, который отображает новый массив по условию функционального аргумента:
Часто удобно реализовать функции поиска с использованием функциональных аргументов, определяющих практически неограниченные условия поиска:
Также мы можем отметить применение функционалов как, например, метода forEach, который применяет функцию к массиву элементов:
Функция применяется к аргументам (к списку аргументов - в применении и к позиционированным аргументам - в вызове):
Отложенные звонки:
Функции обратного вызова:
Создание инкапсулированной области видимости с целью сокрытия вспомогательных объектов:
источник
скрипка
источник
Закрытия являются полезным способом создания генераторы, последовательность увеличивается по требованию:
Различия сводятся к следующему:
Ссылки
источник
В данном примере значение вложенной переменной 'counter' защищено и может быть изменено только с использованием данных функций (приращение, уменьшение). потому что это в закрытии,
источник
Объясняя практическое использование для закрытия в JavaScript ---
Когда мы создаем функцию внутри другой функции, мы создаем замыкание. Замыкания являются мощными, потому что они способны читать и манипулировать данными своих внешних функций. Всякий раз, когда вызывается функция, для этого вызова создается новая область. Локальная переменная, объявленная внутри функции, принадлежит этой области, и к ним можно получить доступ только из этой функции. Когда функция закончила выполнение, область видимости обычно уничтожается.
Простой пример такой функции:
В приведенном выше примере функция buildName () объявляет приветствие локальной переменной и возвращает его. Каждый вызов функции создает новую область видимости с новой локальной переменной. После того, как функция завершена, у нас нет возможности снова обратиться к этой области, поэтому она собирает мусор.
Но как насчет того, когда у нас есть ссылка на эту область?
Давайте посмотрим на следующую функцию:
Функция sayName () из этого примера является замыканием. Функция sayName () имеет собственную локальную область (с приветствием переменной), а также имеет доступ к области действия внешней (включающей) функции. В этом случае переменная приветствие от buildName ().
После выполнения buildName область действия в этом случае не уничтожается. Функция sayMyName () все еще имеет к ней доступ, поэтому она не будет собирать мусор. Однако другого способа доступа к данным из внешней области не существует, кроме замыкания. Закрытие служит шлюзом между глобальным контекстом и внешней областью действия.
источник
Я пытаюсь выучить трудности, и я думаю, что пример, который я создал, является практическим примером использования. Вы можете запустить сниппет и увидеть результат в консоли. у нас есть два отдельных пользователя, которые имеют отдельные данные. Каждый из них может видеть фактическое состояние и обновлять его.
источник