Зачем нужны замыкания? (JavaScript) [дубликат]
Коллеги! Теоретически я как бы понял сущность замыкания: это высшая функция, возвращающая другую, «дочернюю» функцию, при этом должны быть переменные, замкнутые в области видимости «между» высшей и дочерней. Дочерняя функция вызывается в глобальной области и обрабатывает эти переменные и свои аргументы. Как бы создается один пакет из двух «набираемых» в двух независимых вызовах кортежей данных. ВОПРОС: а какова необходимость в замыкании, конкретно, какой род проблем оно решает, какой тип задач, для реализации какого алгоритма нужен?
Отслеживать
Владимир Симиненко
задан 20 дек 2021 в 11:05
Владимир Симиненко Владимир Симиненко
1 2 2 бронзовых знака
А как пользоваться ооп не имея его?
20 дек 2021 в 11:07
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Думаю будет легче понять что это заглянув в историю. Сегодня конечно имея дополнительные конструкции языка это может казаться бесмысленным.
function makeFunc() < var name = "Mozilla"; function displayName() < alert(name); >return displayName; >; var myFunc = makeFunc(); myFunc();
Замыкания на практике.
Замыкания полезны тем, что позволяют связать данные (лексическое окружение) с функцией, которая работает с этими данными. Очевидна параллель с объектно-ориентированным программированием, где объекты позволяют нам связать некоторые данные (свойства объекта) с одним или несколькими методами.
Следовательно, замыкания можно использовать везде, где вы обычно использовали объект с одним единственным методом.
Такие ситуации повсеместно встречаются в web-разработке. Большое количество front-end кода, который мы пишем на JavaScript, основано на обработке событий. Мы описываем какое-то поведение, а потом связываем его с событием, которое создаётся пользователем (например, клик мышкой или нажатие клавиши). При этом наш код обычно привязывается к событию в виде обратного/ответного вызова (callback): callback функция — функция выполняемая в ответ на возникновение события.
Языки вроде Java позволяют нам объявлять частные (private) методы . Это значит, что они могут быть вызваны только методами того же класса, в котором объявлены.
JavaScript не имеет встроенной возможности сделать такое, но это можно эмулировать с помощью замыкания. Частные методы полезны не только тем, что ограничивают доступ к коду, это также мощное средство глобальной организации пространства имён, позволяющее не засорять публичный интерфейс вашего кода внутренними методами классов
что такое замыкание js
«Замыкание» — это способность функции запоминать переменные, которые были определены внутри родительской функции, даже после того, как родительская функция была выполнена.
function createCounter() // переменная, которую нужно запомнить let count = 0; function counter() // увеличиваем нашу запомненную переменную count++; console.log(count); > // возвращаем функцию return counter; > // создаем новую функцию (с замыканием) const incrementCounter = createCounter(); incrementCounter(); // 1 incrementCounter(); // 2 incrementCounter(); // 3
В этом примере мы создали функцию createCounter() , которая создает другую функцию counter() . Внутри функции мы создали переменную count , которая была определена внутри родительской функции. Функция counter() возвращает значение count , увеличивая его на 1 . Когда мы вызываем createCounter() , она возвращает функцию counter() , которая имеет доступ к count благодаря замыканию. Каждый раз, когда мы вызываем incrementCounter() ,
Если мы создадим новый счетчик с помощью функции createCounter() , то отсчет для него начнется заново.
// Создали еще одну новую функци-счетчик const newIncrementCounter = createCounter(); newIncrementCounter(); // 1 newIncrementCounter(); // 2 newIncrementCounter(); // 3
Для чего нужны замыкания (js)?
Читаю о замыканиях, хоть и не с первого раза, но немного стало понятно как это работает. Однако сразу,как у любого новичка, напросился вопрос, а для каких целей конкретно в js существуют замыкания? Объясните,пожалуйста, доступным языком.
- Вопрос задан более трёх лет назад
- 7778 просмотров
2 комментария
Простой 2 комментария
Думаю, не совсем корректный вопрос. Замыкания существуют не для каких-то целей, они просто существуют, потому что это особенности языка. Наверное стоит спросить, для каких целей используются замыкания. Хотя на этот вопрос будет непросто ответить.
Решения вопроса 1

Ну если доступным, языком, то тогда на примере.
Например, надо выводить в лог сообщение, а также номер строки и время прошедшее с момента зарузки страницы.
Если не использовать замыкание, то надо определить следующую функцию
function log(timespan, lineNumber, msg)
и две переменные
var start = Date.now(); var lineNumber = 1;
Вызываем log так
log(Date.now()-start, lineNumber++, "один"); log(Date.now()-start, lineNumber++, "два");
Очевидно, что это неудобно.
Если использовать замыкание, то пишем так
var log = (function () < // функция 1 var start = Date.now(); // текущее значение сохранятся в start var num = 1; // также используется в замыкании в функции 2. return function (msg) < // функция 2 - сохраняется в var log console.log(num++ + " " + (Date.now()-start) + " " + msg); >>)(); // () -- вызываем функцию 1
Вызываем так
log("один"); log("два");
lineNumber timespan msg ------------------------------ 1 0 один 2 1 два
Т.е. замыкание — это способ передачи данных в функцию.
Подробнее о замыканиях см Mozilla Developer Network
Примет взят отсюда
Ответ написан более трёх лет назад
Комментировать
Нравится 15 Комментировать
Ответы на вопрос 2
Замыкание это функция и внешние переменные, которые в нее приходят.
Переменная не приходит — замыкания нет.
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Замыкания в JavaScript.
Допустим, мы вызываем внутри нашего кода какую-то функцию (назовем ее первичной функцией), т.е. какой-то код (назовем его вспомогательным), находящийся в теле этой функции. И этот вспомогательный код объявляет другую функцию (назовем ее вторичной функцией) и возвращает эту вторичную функцию в качестве возвращаемого значения.
Здесь ключевой момент– не в коде создается, а код создает. Т.е. если бы мы не вызвали код первичной функции, то вторичная функция бы не была создана. Ее и в памяти-то нигде не было бы. К ней нельзя было бы обратиться. Интерпретатор не размещает ее в памяти, пока не будет вызвана первичная функция.
В этом вспомогательном коде могут быть объявлены и инициализированы переменные, а внутри тела этой вторичной функции могут быть обращения к этим переменным, т.е. код может захватить некоторые ресурсы и ссылки на часть этих ресурсов передать в функцию.
Тогда эта возвращенная вторичная функция будет иметь такую особенность, что внутри нее будут ссылки на некие ресурсы, находящиеся где-то. И если бы эти ресурсы были удалены, то при запуске этой функции на выполнение произошла бы ошибка (были бы не найдены какие-то затребованные данные). Поэтому когда такая функция объявляется в выполняемом коде (т.е. создается динамически) и при возвращении из кода присваивается какой-то переменной, то чтобы эта операция имела смысл, интерпретатор сохраняет в памяти созданные в коде данные, на которые ссылается эта функция.
Именно память под данные, на которые ссылается вторичная функция, выделенная в момент выполнения кода первичной функции (в этот момент как раз создается и размещается в памяти и вторична функция) сохраняется. Остальная память, временно выделявшаяся при работе кода первичной функции, высвобождается.
Т.е. эту вторичную функцию можно рассматривать просто как обычный объект, содержащий в своих полях некоторые данные. Естественно, пока на этот объект где-то будут оставаться ссылки, будут сохраняться в памяти и данные этого объекта.
Пока где-то в коде существует действующая ссылка на эту вторичную функцию, будут работоспособными и все ссылки внутри этой функции на участки памяти с данными, которые выделялись при создании этой вторичной функции.
Если мы второй раз вызовем первичную функцию, мы создадим уже совершенно другой объект вторичной функции, со своими данными.
Эта вторичная функция, т.е. этот динамически созданный объект, называется, вы не поверите, — замыканием.
Ответ написан более двух лет назад
Комментировать
Нравится 1 Комментировать
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- JavaScript
- +1 ещё
Как объеденить круговой слайдер(диапозон) с полем ввода и кнопками + и -?
- 1 подписчик
- 2 часа назад
- 21 просмотр
Для чего нужны замыкания в javascript
Замыкания в JavaScript используются довольно часто, и вы, наверняка, уже сталкивались с ними. Они позволяют делать код более выразительным и лаконичным. В какой-то степени, замыкания могут показаться сложной темой, но в данной статье мы постараемся разобраться с ними. Перед знакомством с этой темой необходимо хорошо понимать, какие особенности имеет область видимости переменных в JavaScript.
Что такое замыкание
Замыкание — это функция, объявленная внутри другой функции и имеющая доступ к переменным внешней (вмещающей) функции. Замыкание имеет доступ сразу к трем областям видимости:
- к своей собственной области видимости (переменные, объявленные внутри замыкания);
- к области видимости внешней функции (переменные, объявленные внутри внешней функции);
- к глобальной области видимости.
Внутренняя функция имеет доступ не только к переменным внешней функции, но и к параметрам внешней функции. Обратите внимание, что внутренняя функция не может использовать объект arguments внешней функции, однако, имеет доступ к параметрам внешней функции напрямую.
Простыми словами замыкание — это функция, описанная внутри другой функции.
Пример замыкания в JavaScript:
function showName(firstName, lastName) < var nameIntro = "Your name is "; function makeFullName() < return nameIntro + firstName + " " + lastName; >return makeFullName(); > showName("Michael", "Jackson"); // Your name is Michael Jackson
Замыкания также нередко используются в jQuery:
$(function() < var selections = []; $('.niners').click(function() < selections.push(this.prop('name')); >); >);
Правила и побочные эффекты замыканий
Замыкание имеет доступ к переменным внешней функции даже после ее выполнения.
Одним из наиболее тонких моментов, связанных с замыканиями, является то, что внутренняя функция продолжает иметь доступ к области видимости внешней даже после того, как внешняя выполнилась.
Это означает, что даже после того, как внешняя функция выполнилась, внутренняя функция все еще может быть вызвана и она все еще имеет доступ к переменным внешней функции.
Замыкания хранят ссылки на переменные внешней функции, а не фактические значения.
Такая интересная особенность позволяет описывать приватные переменные. Это способ впервые был предложен Дугласом Крокфордом:
function user() < var name = 'Unknown'; return < getName: function() < return name; >, setName: function(newName) < name = newName; >> > var testUser = user(); testUser.getName(); // Unknown testUser.setName('John Smith'); // Изменяем значение приватной переменной testUser.getName(); // John Smith
Побочные эффекты, связанные с замыканиями
Т.к. замыкание хранит ссылку на переменную внешней функции, а не фактическое значение, могут возникать побочные эффекты, связанные с тем, что замыкание изменяет внешнюю переменную:
function userIdGenerator(users) < var i; var uniqueId = 100; for (i = 0; i < users.length; i++) < users[i]['id'] = function() < return uniqueId + i; >> return users; > var testUsers = [< name: "Smith", id:0 >, < name: "Johnson", id:0 >, < name: "Thompson", id:0 >]; var testUsersIds = userIdGenerator(testUsers); var firstId = testUsersIds[0]; console.log(firstId.id()); // 103
В предыдущем примере, к тому времени, когда вызывается анонимная функция, значение i становится равно 3 (длина массива). Число 3 было прибавлено к значению переменной uniqueId, тем самым для всех элементов массива testUsers значение id стало равно 103, вместо предполагаемых 100, 101, 102.
Решением предыдущей проблемы может быть шаблон немедленно вызываемой функции (Immediately Invoked Function Expression — IIFE):
function userIdGenerator(users) < var i; var uniqueId = 100; for (i = 0; i < users.length; i++) < users[i]['id'] = function(j) < return function() < return uniqueId + j; >(); > (i); > return users; > var testUsers = [< name: "Smith", id:0 >, < name: "Johnson", id:0 >, < name: "Thompson", id:0 >]; var testUsersIds = userIdGenerator(testUsers); var firstId = testUsersIds[0]; console.log(firstId.id); // 100 var secondId = testUsersIds[1]; console.log(secondId.id); // 101
Заключение
Замыкания — это очень интересный и крайне полезный прием программирования. Суть замыкания можно выразить так: в функции доступны все переменные той области видимости, в которой она была определена.
Замыкания позволяют реализовывать аналог приватных переменных, минимизировать выход переменных в глобальную область видимости. С другой стороны, неаккуратное использование замыканий может привести к побочным эффектам, описанным выше. Поэтому использовать их стоит крайне внимательно.
