с.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; };
// Метод записи сохраняет значение или возбуждает исключение,
// если функция проверки отвергает это значение.
o["set" + name] = function(v) {
if (predicate && !predicate(v))
throw Error("set" + name + недопустимое значение + v);
else
value = v;
};
}
// Следующий фрагмент демонстрирует работу метода addPrivateProperty().
var о = {}; // Пустой объект
// Добавить к свойству методы доступа с именами getName() и setName()
// Обеспечить допустимость только строковых значений
addPrivateProperty(o, "Name", function(x) { return typeof x == "string"; });
o.setName("Frank"); // Установить значение свойства
console.log(o.getName()); // Получить значение свойства
о.setName(0); // Попробовать установить значение свойства неверного типа
Мы увидели несколько примеров, когда замыкания определяются в одной и той же цепочке областей видимости и совместно используют одну локальную пере¬менную или переменные. Важно знать и уметь пользоваться этим приемом, но но менее важно уметь распознавать ситуации, когда замыкания получают перемен¬ную в совместное использование по ошибке. Рассмотрим следующий пример: