• Если объект нерасширяемый, можно изменить существующие собственные свойства этого объекта, но нельзя добавить в него новые свойства.
• Если свойство недоступно для настройки, нельзя изменить его атрибуты configurable и enumerable.
• Если свойство с методами доступа недоступно для настройки, нельзя изменить его методы чтения и записи и нельзя превратить его в простое свойство с данными.
• Если свойство с данными недоступно для настройки, нельзя превратить его в свойство с методами доступа.
• Если свойство с данными недоступно для настройки, нельзя изменить значение его атрибута
writable
с
false
на
true
, но его можно Изменить с
true
на
false
.
• Если свойство с данными недоступно для настройки и для записи, нельзя изменить его значение. Однако изменить значение свойства, недоступного для записи можно, если оно доступно для настройки (потому что свойство можно сделать доступным для записи, изменить его значение и затем опять сделать свойство доступным только для чтения).
Пример 6.2 включает функцию
extend,
которая копирует свойства из одного объекта в другой. Эта функция просто копирует имена и значения свойств и игнорирует их атрибуты. Кроме того, она не копирует методы чтения и записи из свойств с методами доступа, а просто преобразует их в свойства со статическими данными. В примере 6.3 показана новая версия
extend,
которая копирует все атрибуты свойств с помощью
Object.getOwnPropertyDescriptor
и
Object.defineProperty.
Но на этот раз данная версия оформлена не как функция, а как новый метод объекта и добавляется в
Object.prototype
как свойство, недоступное для перечисления.
Пример 6.3. Копирование атрибутов свойств
/*
* Добавляет неперечислимый метод extend в Object.prototype.
* Этот метод расширяет объекты возможностью копирования свойств из объекта,
* переданного в аргументе. Этот метод копирует не только значение свойств,
* но и все их атрибуты. Из объекта в аргументе копируются все собственные
* свойства (даже недоступные для перечисления), за исключением одноименных
* свойств, имеющихся в текущем объекте.
*/
Object.defineProperty(Object.prototype,
"extend", // Определяется Object.prototype.extend
{
writable: true,
enumerable: false, // Сделать неперечислимым
configurable: true,
value: function(o) { // Значением свойства является данная функция
//
Получить все собственные свойства, даже неперечислимые
var names = Object.getOwnPropertyNames(o);
// Обойти их в цикле
for(var і = 0: і < names.length; i++) {
// Пропустить свойства, уже имеющиеся в данном объекте
if (names[i] in this) continue;
// Получить дескриптор свойства из о
var desc = Object.getOwnPropertyDescriptor(o,names[i]);
// Создать с его помощью свойство в данном объекте
Object.defineProperty(this, names[i], desc);
}
}
});
6.7.1. Устаревшие приемы работы с методами чтения и записи
Синтаксис определения свойств с методами доступа в литералах объектов, описанный разделе 6.6, позволяет определять свойства с методами в новых объектах, но, он не дает возможности получать методы чтения и записи и добавлять новые свойства с методами доступа к существующим объектам. В ECMAScript 5 для этих целей можно использовать
Object.getOwnPropertyDescriptor
и
Object.defineProperty
.
Большинство реализаций JavaScript (за исключением веб-броузера IE) поддерживали синтаксис
get
и
set
в литералах объектов еще до принятия стандарта ECMAScript 5. Эти реализации поддерживают нестандартный, устаревший API для получения и назначения методов чтения и записи. Этот API состоит из четырех методов, доступных во всех объектах.
__lookupGetter__
и
__lookupSetter__
возвращают методы чтения и записи для указанного свойства. А методы
__defineGetter__
и
__defineSetter__
позволяют определить метод чтения или записи:
в первом аргументе они принимают имя свойства, а во втором - метод чтения или записи. Имена всех этих методов начинаются и оканчиваются двумя символами подчеркивания, чтобы показать, что они являются нестандартными методами. Эти нестандартные методы не описываются в справочном разделе.
6.8. Атрибуты объекта
Все объекты имеют атрибуты
prototype
,
class
и
extensible
. Все эти атрибуты описываются в подразделах ниже; в них также рассказывается, как получать и изменять значения атрибутов (если это возможно).