Книга: Выразительный JavaScript
Замыкания
Замыкания
Возможность использовать вызовы функций как переменные вкупе с тем фактом, что локальные переменные каждый раз при вызове функции создаются заново, приводит нас к интересному вопросу. Что происходит с локальными переменными, когда функция перестаёт работать?
Следующий пример иллюстрирует этот вопрос. В нём объявляется функция wrapValue
, которая создаёт локальную переменную. Затем она возвращает функцию, которая читает эту локальную переменную и возвращает её значение.
function wrapValue(n) {
var localVariable = n;
return function() { return localVariable; };
}
var wrap1 = wrapValue(1);
var wrap2 = wrapValue(2);
console.log(wrap1());
// ? 1
console.log(wrap2());
// ? 2
Это допустимо и работает так, как должно – доступ к переменной остаётся. Более того, в одно и то же время могут существовать несколько экземпляров одной и той же переменной, что ещё раз подтверждает тот факт, что с каждым вызовом функции локальные переменные пересоздаются.
Эта возможность работать со ссылкой на какой-то экземпляр локальной переменной называется замыканием. Функция, замыкающая локальные переменные, называется замыкающей. Она не только освобождает вас от забот, связанных с временем жизни переменных, но и позволяет творчески использовать функции.
С небольшим изменением мы превращаем наш пример в функцию, умножающую числа на любое заданное число.
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
var twice = multiplier(2);
console.log(twice(5));
// ? 10
Отдельная переменная вроде localVariable
из примера с wrapValue
уже не нужна. Так как параметр – сам по себе локальная переменная.
Потребуется практика, чтобы начать мыслить подобным образом. Хороший вариант мысленной модели – представлять, что функция замораживает код в своём теле и обёртывает его в упаковку. Когда вы видите return function(...) {...}
, представляйте, что это пульт управления куском кода, замороженным для употребления позже.
В нашем примере multiplier
возвращает замороженный кусок кода, который мы сохраняем в переменной twice
. Последняя строка вызывает функцию, заключённую в переменной, в связи с чем активируется сохранённый код (return number * factor;
). У него всё ещё есть доступ к переменной factor
, которая определялась при вызове multiplier
, к тому же у него есть доступ к аргументу, переданному во время разморозки (5)
в качестве числового параметра.
- Глава 7 Процесс замыкания обратной связи
- Разработка процесса замыкания обратной связи
- 8.6. Замыкания
- Что происходит после замыкания обратной связи?
- Пример из практики: процесс замыкания обратной связи с корпоративными клиентами в компании BearingPoint
- 4. Полнота системы правил Армстронга
- Функции как значения
- Глава 5 От «брендовых бульдозеров» к глобальным партнерам по распространению Один в поле не воин
- Лекция № 12. Связи классов сущностей
- Лекция 9. Наследование и замыкание
- Глава 6 Настраиваем автоответчики (универсальный метод внедрения автоматических рассылок)