danielnewman
@danielnewman
Front-end

Как работает замыкание вообще и в JavaScript, в частности?

В mozilla.org произошла очередная попытка объяснить мне замыкания, об которое бился, на круг, не меньше дня:

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12


Наконец, вроде бы, понял. Вот мой вариант лаконичного объяснения замыкания (closure):
function boltun(secret) {
  return function(question) {
    answer = question + '? ' + secret + '!';
    return answer;
  }
}

var shpionOne = boltun('e=mc²');
shpionOne('Болтун');


Вроде бы понял, но правильно ли? Болтун — находка для шпиона. Повявился ряд вопросов:

— Достаточно ли "выразителен" такой код, в плане понимания идеи замыкания?
— Есть ли иной способ "выудить тайны болтуна"?
— Является ли closure самостоятльным паттерном и как выглядит паттерн "одиночка" (singleton)?

Буду очень признателен.
  • Вопрос задан
  • 961 просмотр
Решения вопроса 1
Petroveg
@Petroveg
Миром правят маленькие с#@&ки
Пример, который вы привели, относится больше к каррированию (каррингу).
Вы передали некое значение, которое получила в свой контекст внутренняя функция, которая и вернулась.

Замыкание ли это? Безусловно. Почитайте про лексический контекст у Ильи Кантора. Лексический контекст зависит от способа создания (FD, FE или вызов конструктора Function).

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

Closure — не паттерн, а реализация. К паттерну Singlton не имеет отношения.
Тык, пык.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
danielnewman
@danielnewman Автор вопроса
Front-end
Упиваюсь Флэнигоном "Полное руководство". Там есть хорошее объяснение и краткая врезка. Полное описание вышлю по просьбе в личку, а врезку - врезку сюда выложу.

Реализация замыканий

Понять суть замыканий будет совсем несложно, если усвоить правило лек-
сической области видимости: во время выполнения функции используется
цепочка областей видимости, которая действовала в момент ее определе-
ния. Однако некоторые программисты испытывают сложности при освое-
нии замыканий, потому что не до конца понимают особенности реализа-
ции. Известно, думают они, что локальные переменные, объявленные во
внешней функции, прекращают свое существование после выхода из внеш-
ней функции, но тогда как вложенная функция может использовать цепоч-
ку областей видимости, которая больше не существует? Если вы задавали
себе такой вопрос, значит, у вас наверняка есть опыт работы с низкоуров-
невыми языками программирования, такими как C, и аппаратными архи-
тектурами, использующими стек: если локальные переменные размещать
на стеке, они действительно прекращают свое существование после завер-
шения функции.
Но вспомните определение цепочки областей видимости из раздела 3.10.3.
Там она описывалась как список объектов, а не стек. Каждый раз, когда
интерпретатор JavaScript вызывает функцию, он создает новый объект для
хранения локальных переменных этой функции, и этот объект добавляет-
ся в цепочку областей видимости. Когда функция возвращает управление,
этот объект удаляется из цепочки. Если в программе нет вложенных функ-
ций и нет ссылок на этот объект, он будет утилизирован сборщиком мусо-
ра. Если в программе имеются вложенные функции, тогда каждая из этих
функций будет владеть ссылкой на свою цепочку областей видимости, а це-
почка будет ссылаться на объекты с локальными переменными. Если объ-
екты вложенных функций существуют только в пределах своих внешних
функций, они сами будут утилизированы сборщиком мусора, а вместе
с ними будут утилизированы и объекты с локальными переменными, на
которые они ссылались. Но если функция определяет вложенную функ-
цию и возвращает ее или сохраняет в свойстве какого-либо объекта, то об-
разуется внешняя ссылка на вложенную функцию. Такой объект вложен-
ной функции не будет утилизирован сборщиком мусора, и точно так же не
будет утилизирован объект с локальными переменными, на который она
ссылается.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы