Дескрипторы свойств и полезные методы объектов

Код
const user = {
  name: 'Alex',
  surname: 'Smith',
  birthday: '20/04/1993',
  showMyPublicData: function() {
  console.log(`${this.name} ${this.surname}`);
  }
}

У каждого из свойств объекта помимо значения есть специальные атрибуты (флаги).

writable - если установлено в true, то это свойство объекта можно будет изменить, если false - только для чтения

enumerable - если установлено в true, то это свойство будет перечисляться в циклах, если false - будет игнорироваться

configurable - если установлено в true, то свойство можно будет удалить, а его атрибуты можно изменять, иначе сделать этого будет нельзя

По умолчанию для всех создаваемых свойств объекта, флаги стоят в позиции true.

Выведем в консоль флаги свойства name

Код
console.log(Object.getOwnPropertyDescriptor(user, 'name'));

Цитата
Object
configurable: true
enumerable: true
value: "Alex"
writable: true
[[Prototype]]: Object

Изменим значение флагов этого свойства:

Код
Object.defineProperty(user, 'name', {writable: false});

Мы изменили возможность редактирования данного свойства, пробуем перезаписать его значение:

Код
user.name = "John";

И получаем ошибку, так как наше свойство теперь стало только для чтения (read only):

Цитата
Uncaught TypeError: Cannot assign to read only property 'name' of object

При помощи defineProperty можно создавать новые свойства, с заданными параметрами флагов, причем свойства, которых еще нет в данном объекте. Если при этом не устанавливать значения флагов, то они по умолчанию станут false.

Например:

Код
Object.defineProperty(user, 'gender', {value: 'male'});

Выведем в консоль флаги созданного нового свойства

Код
console.log(Object.getOwnPropertyDescriptor(user, 'gender'));

Цитата
{
value: 'male',
writable: false,
enumerable: false,
configurable: false
}

Практическое применение: допустим, стоит задача, что когда пользователь заполняет анкету, дату рождения он может указать только один раз, без возможности её дальнейшего редактирования.

Код
Object.defineProperty(user, 'birthday', {writable: false});

Можно вообще сделать это в динамике, изначально убрав из объекта свойство birthday, а потом добавлять его, получая значение от пользователя и при этом сразу установить нужные флаги:

Код
Object.defineProperty(user, 'birthday', {value: prompt('Введите дату рождения'), enumerable: true, configurable: true});

Выведем в консоль флаги свойства birthday
Код
console.log(Object.getOwnPropertyDescriptor(user, 'birthday'));

Цитата
{value: '02.12.1974', writable: false, enumerable: true, configurable: true}

Пример 2: допустим, нам нужно куда-то выводить данные из этого объекта. При этом данные нужны только имя, фамилия, дата рождения. Но в объекте также есть и метод, который также пойдёт в работу.
Как сделать так, чтобы при переборе не было видно метода?

Установить ему нужный флаг:

Код
Object.defineProperty(user, 'showMyPublicData', {enumerable: false});

for (let key in user) console.log(key);

Цитата
name
surname

Можно редактировать сразу несколько свойств с помощью метода Object.defineProperties

Код
Object.defineProperties(user, {
  name: {writable: false},
  surname: {writable: false}
});

Полезные методы объектов


Метод Object.keys() возвращает массив из собственных перечисляемых свойств переданного объекта, в том же порядке, в котором они бы обходились циклом for...in

Код
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.keys(obj)); // ['0', '1', '2']

Метод Object.values() возвращает массив значений перечисляемых свойств объекта в том же порядке что и цикл for...in.

Код
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.values(obj)); // ['a', 'b', 'c']

Object.entries() метод возвращает массив собственных перечисляемых свойств указанного объекта в формате [key, value], в том же порядке, что и в цикле for...in

Код
var obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]


Object.keys()Object.values()Object.entries()

Всего комментариев: 0

Имя *:
Email *:
Код *:
Хостинг от uCoz