9.8.1. Определение неперечислимых свойств

Класс Set, представленный в примере 9.6, вынужден использовать уловку, чтобы обеспечить возможность сохранения объектов: он добавляет свойство «object id» ко всем объектам, добавляемым в множество. Если позднее в каком-то другом месте программы будет выполнен обход свойств этого объекта с помощью цикла for/in, это свойство будет обнаружено. Стандарт ECMAScript 5 позволяет исключить такую возможность, сделав свойство неперечислимым. В примере 9.17 демонстрируется, как это сделать с помощью Object.defineProperty(), а также показывает, как определить метод чтения и как проверить возможность расширения объекта.

Пример 9.17. Определение неперечислимых свойств

// Обертывание программного код функцией позволяет определять переменные

// в области видимости функции

(function() {

  // Определить свойство objectId как неперечислимое и наследуемое

  // всеми объектами. При попытке получить значение этого свойства

  // вызывается метод чтения. Свойство не имеет метода записи, поэтому

  // оно доступно только для чтения. Свойство определяется как ненастраиваемое,

  // поэтому его нельзя удалить.

  Object.defineProperty(Object.prototype, "objectld", {

    get: idGetter, // Метод чтения значения

    enumerable: false, // Неперечислимое

    configurable: false // He может быть удалено

  });

  // Функция чтения, которая вызывается при попытке получить значение

  // свойства objectld

  function idGetter() { // Функция чтения, возвращающая id

    if (!(idprop in this)) { // Если объект еще не имеет id

      if (!Object.isExtensible(this)) // И если можно добавить свойство

        throw Error("Нельзя определить id нерасширяемого объекта”);

      Object.defineProperty(this, idprop, { // Добавить его.

        value: nextid++, // Значение

        writable: false, // Только для чтения

        enumerable: false, // Неперечислимое

        configurable: false // Неудаляемое

      }):

    }

    return this[idprop]; // Вернуть существующее или новое значение

  };

  // Следующие переменные используются функцией idGetter() и являются

  // частными для этой функции

  var idprop = "|**objectId**|"; // Предполагается, что это свойство

  // больше нигде не используется

  var nextid = 1; // Начальное значение для id

}()); // Вызвать функцию-обертку, чтобы выполнить программный код