Атрибуты свойств объектов в JavaScript
JavaScript

Атрибуты свойств объектов в JavaScript

Свойства объекта часто определяют как пары «ключ-значение». По большому счету это не совсем так. Кроме собственно имени и значения свойства также имеют так называемые атрибуты. В спецификации ECMAScript 3 атрибуты свойств не доступны для чтения и записи, однако, в ECMAScript 5 предусмотрены методы для работы с атрибутами свойств.

Типы свойств объекта в JavaScript

В JavaScript существует три типа свойств:

Свойства с данными — это обычные свойства, с которыми мы привыкли работать. К примеру, рассмотрим объект animal:


var animal = {
    type: 'cat',
    name: 'Tom',
    color: 'gray'
};

Мы можем получить значение свойства:


console.log(animal.color); // gray
console.log(animal['color']); // gray

Или установить, изменить значение свойства:


animal.color = 'white';
animal['color'] = 'white';

Свойства с методами доступа — эти свойства имеют методы get и set для чтения и записи свойства соответственно.


var circle = {
    x: 0,
    y: 0,
    r: 15
};

/* Добавим свойство area к объекту circle */
Object.defineProperty(circle, 'area', {
    get: function() { 
        return 3.14 * this.r * this.r; 
    },
    set: function(s) { 
        this.r = Math.sqrt(s / 3.14); 
    }
});

console.log(circle.r); // 15
console.log(circle.area); // 706.5

// изменим значение свойства area
circle.area = 1000;
console.log(circle.r); // 17.845765256206242
console.log(circle.area); // 1000

Внутренние свойства — свойства, используемые в спецификации. К таким свойствам относятся свойства prototype и extensible. Свойство prototype объекта может быть получено с помощью метода Object.getPrototypeOf(), а установлено при создании объекта с помощью метода Object.create().

Свойство extensible определяет, разрешено ли добавлять свойства к данному объекту, и по умолчанию имеет значение true. Получить значение этого свойства можно с помощью метода Object.isExtensible(), а установить значение равное false с помощью метода Object.preventExtensions() (если один раз установить значение свойства объекта extensible равное false, поменять обратно его уже нельзя).

Атрибуты свойств

Специфичными атрибутами для свойств с данными являются следующие атрибуты:

  • value — содержит непосредственно данные
  • writable — определяет, доступно ли данное свойство для записи (по умолчанию, true)

Специфичными атрибутами для свойств с методами доступа являются:

  • set — содержит setter, функцию, которая вызывается при записи свойства
  • get — содержит getter, функцию, которая вызывается при чтении свойства

Общие атрибуты свойств:

  • enumerable — определяет доступность свойства для перечисления
  • configurable — определяет доступность свойства для изменения (например, может ли свойство быть удалено, может ли быть изменен какой-либо атрибут свойства).

Дескрипторы свойств

Дескриптор свойства объекта описывает атрибуты свойства в виде объекта, именами свойств этого объекта являются названия атрибутов, а значениями — значения атрибутов. Получить дескриптор свойства можно с помощью метода Object.getOwnPropertyDescriptor().

Получим дескрипторы свойств объекта circle из предыдущего примера:


console.log(Object.getOwnPropertyDescriptor(circle, 'r'));
/* Получим объект
{
    configurable: true,
    enumerable: true,
    value: 15,
    writable: true
}
*/

console.log(Object.getOwnPropertyDescriptor(circle, 'area'));
/* Получим
{ 
    configurable: false, 
    enumerable: false, 
    get: function(),
    set: function(s)
}
*/

С дескрипторами свойств также работают следующие функции:

Object.defineProperty() — создает или изменяет свойство объекта, возвращает модифицированный объект:


var obj = Object.defineProperty({}, 'foo', {
    value: 123,
    enumerable: true
});

Object.defineProperties() — метод аналогичен defineProperty, но позволяет оперировать сразу с несколькими свойствами. Также возвращает модифицированный объект:


var obj = Object.defineProperties({}, {
    foo: { value: 123, enumerable: true },
    bar: { value: 'abc', enumerable: true }
});

Object.create() — создание объекта. В качестве первого параметра принимает объект-прототип создаваемого объекта, в качестве второго необязательного параметра — список свойств объекта:


var obj = Object.create(Object.prototype, {
    foo: { value: 123, enumerable: true },
    bar: { value: 'abc', enumerable: true }
});

Перечислимые свойства объекта

Атрибут enumerable определяет, доступно ли свойство для перечисления, а именно, будет ли оно доступно в циклах for/in и методе Object.keys(), все остальные операции игнорирую атрибут enumerable. Рассмотрим пример:


var proto = Object.defineProperties({}, {
    foo: { value: 1, enumerable: true },
    bar: { value: 2, enumerable: false }
});
var obj = Object.create(proto, {
    baz: { value: 1, enumerable: true },
    qux: { value: 2, enumerable: false }
});

/* в цикле for/in доступны только enumerable-свойства, как собственные, так и унаследованные */
for (var x in obj) {
    console.log(x); // baz foo
}

/* метод Object.keys возвращает только собственные enumerable-свойства объекта */
Object.keys(obj) // baz

Если необходимо получить все имена собственных свойств объекта, можно использовать метод Object.getOwnPropertyNames().

Заключение

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

Мы также рассмотрели понятие дескриптора свойства. Дескриптор свойства описывает свойство как объект, свойствами которого являются атрибуты. В спецификации ECMAScript 5 предусмотрен ряд методов, позволяющих получать и настраивать атрибуты свойств.

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться