Скрытые переменные, такие как counter, не являются исключительной собственностью единственного замыкания: в одной и той же внешней функции вполне возможно определить две или более вложенных функций, которые будут совместно использовать одну цепочку областей видимости. Рассмотрим следующий пример:
function counter { var n = 0;
return {
count: function { return n++; },
reset: function { n = 0; }
};
}
var c = counter, d = counter; //
Создать два счетчика
c.count // => 0
d.count // => 0: они действуют независимо
с.reset // методы reset и count совместно
// используют одну переменную
c.count // => 0: сброс счетчика с
d.count // => 1: не оказывает влияния на счетчик d
Функция
counter
возвращает объект «счетчика». Этот объект имеет два метода:
count,
возвращающий следующее целое число, и
reset,
сбрасывающий счетчик в начальное состояние. В первую очередь следует запомнить, что два метода совместно используют одну и ту же частную переменную n. Во-вторых, каждый вызов функции
counter
создает новую цепочку областей видимости и новую скрытую переменную. То есть, если вызвать функцию
counter
дважды, она вернет два объекта-счетчика с различными скрытыми переменными. Вызов методов
count
и
reset
одного объекта-счетчика не оказывает влияния на другой.
Важно отметить, что описанный прием образования замыканий можно использовать в комбинации с приемом определения свойств с методами доступа. Следующая версия функции
counter
является вариацией примера, представленного в разделе 6.6, но здесь для хранения скрытой информации вместо обычного свойства объекта используются замыкания:
function counter(n) { // Аргумент n функции - скрытая переменная
return {
// Метод чтения свойства возвращает и увеличивает переменную счетчика,
get count { return n++; },
// Метод записи в свойство не позволяет уменьшать значение n
set count(m) {
if (m >= n)
n = m;
else throw Error( "значение счетчика нельзя уменьшить");
}
};
}
var с = counter(1000);
с.count // => 1000
с.count // => 1001
с.count = 2000
с.count // => 2000
с.count = 2000 // =>
Ошибка!
Обратите внимание, что эта версия функции
counter
не объявляет локальную переменную. Для сохранения информации она просто использует параметр n, доступный обоим методам доступа к свойству. Это позволяет программе, вызывающей
counter,
определять начальное значение скрытой переменной.
В примере 8.4 демонстрируется обобщение приема совместного использования скрытой информации в замыканиях. Этот пример определяет функцию addPrivateProperty, которая в свою очередь определяет скрытую переменную и две вложенные функции для чтения и записи значения этой переменной. Она добавляет эти вложенные функции как методы указанного вами объекта:
Пример 8.4. Реализация методов доступа к частному свойству с использованием замыканий
// Эта функция добавляет методы доступа к свойству с заданным именем объекта о.
// Методы получают имена вида get<name> и set<name>. Если дополнительно предоставляется
// функция проверки, метод записи будет использовать ее для проверки значения
// перед сохранением. Если функция проверки возвращает false,
// метод записи генерирует исключение.
//
// Необычность такого подхода заключается в том, что значение свойства,
// доступного методам, сохраняется не в виде свойства объекта о, а в виде
// локальной переменной этой функции. Кроме того, методы доступа также определяются
// внутри этой функции и потому получают доступ к этой локальной переменной.
// Это означает, что значение доступно только этим двум методам и не может быть
// установлено или изменено иначе, как методом записи,
function addPrivateProperty(o, name, predicate) {
var value; // Это значение свойства
// Метод чтения просто возвращает значение.
о["get" + name] = function { return value; };
// Метод записи сохраняет значение или возбуждает исключение,