Выбрать главу

• добавлять методы в объекты-прототипы и делать их неперечислимыми, подобно встроенным методам;

• «ограничивать» возможности объектов за счет определения свойств, которые не могут изменяться или удаляться.

Для целей данного раздела мы будем рассматривать методы чтения и записи свойств с методами как атрибуты свойств. Следуя этой логике, можно даже сказать, что значение свойства с данными также является атрибутом. Таким образом, свойства имеют имя и четыре атрибута. Четырьмя атрибутами свойств с данными являются: значение (value), признак доступности для записи (writable), признак доступности для перечисления (enumerable) и признак доступности для настройки (configurable). В свойствах с методами доступа отсутствуют атрибуты value и writable: их доступность для записи определяется наличием или отсутствием метода записи. Поэтому четырьмя атрибутами свойств с методами доступа являются: метод чтения (get), метод записи (set), признак доступности для перечисления (enumerable) и признак доступности для настройки (configurable).

Методы получения и записи значений атрибутов свойств, предусмотренные стандартом ECMAScript 5, используют объект, называемый дескриптором свойства (property descriptor), представляющий множество из четырех атрибутов. Объект дескриптора свойства обладает свойствами, имена которых совпадают с именами атрибутов свойства, которое он описывает. То есть объекты-дескрипторы свойств с данными имеют свойства с именами value, writable, enumerable и configurable. А дескрипторы свойств с методами доступа вместо свойств value и writable имеют свойства get и set. Свойства writable, enumerable и configurable являются логическими значениями, а свойства get и set - функциями.

Получить дескриптор свойства требуемого объекта можно вызовом Object.get-OwnPropertyDescriptor():

// Вернет {value: 1, writable:true, enumerable:true, configurable:true}

Object.getOwnPropertyDescriptor({x:1}, "x");

// Теперь получим свойство octet объекта random, объявленного выше.

// Вернет { get: /*func*/. set:undefined, enumerable:true, configurable:true}

Object.getOwnPropertyDescriptor(random, "octet");

// Вернет undefined для унаследованных и несуществующих свойств.

Object.getOwnPropertyDescriptor({}, "х"); // undefined, нет такого свойства

Object.getOwnPropertyDescriptor({}, "toString"); // undefined, унаследованное

Как можно заключить из названия метода, Object.getOwnPropertyDescriptor() работает только с собственными свойствами. Чтобы получить атрибуты унаследованного свойства, необходимо явно выполнить обход цепочки прототипов (смотрите описание Object.getPrototypeOf() в разделе 6.8.1).

Чтобы изменить значение атрибута свойства или создать новое свойство с заданными значениями атрибутов, следует вызвать метод Object.defineProperty(), передав ему объект, в котором требуется выполнить изменения, имя создаваемого или изменяемого свойства и объект дескриптора свойства:

var о = {}; // Создать пустой объект без свойств

// Создать неперечислимое простое свойство х со значением 1.

Object.defineProperty(o, "х", { value : 1,

    writable: true, enumerable: false, configurable: true}):

// Убедиться, что свойство создано и является неперечислимым

о.х;           // => 1

Object.keys(o) // => []

// Теперь сделать свойство х доступным только для чтения