У замыканий есть два важных свойства.
1. Замыкание может обращаться к переменным своей внешней функции даже после ее окончания выполнения.
На практике это означает что даже после того как выполнение внешней функции завершено, внутренняя все еще может быть вызвана и имеет доступ к переменным внешней функции.
Давайте рассмотрим пример:
function pirate() {
var pirateName = "noname";
return {
getName: function() {
return pirateName;
},
setName: function(newName) {
pirateName = newName;
}
}
}
Мы описали функцию с двумя замыканиями: одно возвращает значение переменной из вызывающей функции, второе - изменяет его. Посмотрим, что получится при практическом использовании:
var newPirate = pirate();
console.log(newPirate.getName()); // Выводим текущее содержимое переменной - там изначальный "noname"
newPirate.setName("Jack Sparrow"); //Изменяем значение переменной на "Jack Sparrow"
console.log(newPirate.getName()); //Выводим текущее содержимое переменной - получаем "Jack Sparrow"
В данном примере мы видим что замыкания получили доступ к переменной внешней функции после ее завершения.
2. Замыкания хранят не содержимое переменных внешней функции, а ссылки на эти переменные.
Давайте в этом контексте рассмотрим классический пример замыкания, описываемый в большинстве источников - счетчик.
function makeCounter(initialValue) {
var currentState = initialValue;
return function () {
currentState = currentState + 1;
return currentState;
}
}
В данном случае мы описали функцию, внутри которой находится замыкание, увеличивающее каждый раз счетчик и возвращающее его.
Давайте посмотрим, что получится если вызывать ее много раз пордряд.
var myCounter = makeCounter(5); // Создаем экземпляр счетчика и устанавливаем его начальное значение = 5
console.log(myCounter()); // В консоль будет выведено значение 6
console.log(myCounter()); // В консоль будет выведено значение 7
console.log(myCounter()); // В консоль будет выведено значение 8