JavaScript. Подробное руководство, 6-е издание, стр. 70

Методы получения и записи значений атрибутов свойств, предусмотренные стандартом ECMAScript 5, используют объект, называемый дескриптором свойства (

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

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

<b>Object.get-OwnPropertyDescriptor():</b>

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

<b>Object.getOwnPropertyDescriptor({x:1}, &quot;x&quot;);</b>

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

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

<b>Object.getOwnPropertyDescriptor(random, &quot;octet&quot;);</b>

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

<b>Object.getOwnPropertyDescriptor({}, &quot;х&quot;); // undefined, нет такого свойства</b>

<b>Object.getOwnPropertyDescriptor({}, &quot;toString&quot;); // undefined, унаследованное</b>

Как можно заключить из названия метода,

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

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

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

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

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

<b>Object.defineProperty(o, &quot;х&quot;, { value : 1,</b>

<b>    writable: true, enumerable: false, configurable: true}):</b>

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

<b>о.х;           // =&gt; 1</b>

<b>Object.keys(o) // =&gt; []</b>

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

<b>Object.defineProperty(o, &quot;х&quot;, { writable: false });</b>

<b>// Попытаться изменить значение свойства</b>

<b>о.х = 2; // Неудача, в строгом режиме возбудит ТуреЕrror</b>

Дескриптор свойства, передаваемый методу

<b>Object.defineProperty(),</b>
необязательно должен иметь все четыре атрибута. При создании нового свойства отсутствующие атрибуты получат значение
<b>false</b>
или
<b>undefined</b>
. При изменении существующего свойства для отсутствующих атрибутов будут сохранены текущие значения. Обратите внимание, что этот метод изменяет существующее собственное свойство или создает новое собственное свойство - он не изменяет унаследованные свойства.

Если возникнет необходимость создать или изменить сразу несколько свойств, можно воспользоваться методом

<b>Object.defineProperties().</b>
Первым аргументом ему передается объект, который требуется изменить. Вторым аргументом - объект, отображающий имена создаваемых или модифицируемых свойств в дескрипторы этих свойств. Например:

<b>var р = Object.defineProperties({},{</b>

<b>  х:{ </b>

<b>    value: 1, </b>

<b>    writable: true,</b>

<b>    enumerable:true, </b>

<b>    configurable:true </b>

<b>  }, </b>

<b>  y:{ </b>

<b>    value: 1,</b>

<b>    writable: true,</b>

<b>    enumerable:true,</b>

<b>    configurable:true },</b>

<b>  r:{</b>

<b>    get: function() { return Math.sqrt(this.x*this.x + this.y*this.y) },</b>

<b>    enumerable:true,</b>

<b>    configurable:true</b>

<b>  }</b>

<b>});</b>

В этом примере все начинается с пустого объекта, в который затем добавляются два свойства с данными и одно свойство с методами доступа, доступное только для чтения. Он опирается на тот факт, что

<b>Object.defineProperties()</b>
возвращает модифицированный объект (подобно методу
<b>Object.defineProperty()</b>
).