Learn JavaScript

Object.getOwnPropertyDescriptor() - метод для получения дескриптора свойства объекта в JavaScript

Object.getOwnPropertyDescriptor() возвращает дескриптор свойства объекта.

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

  • можно ли его менять
  • видно ли оно в перечислении
  • можно ли его перенастраивать
  • является ли оно геттером или сеттером

Синтаксис

Object.getOwnPropertyDescriptor(obj, propertyName)

obj - объект, у которого нужно посмотреть свойство.

propertyName - имя свойства.

Что делает Object.getOwnPropertyDescriptor()

Метод возвращает объект с описанием свойства.

const user = {
  name: "Anna",
};

console.log(Object.getOwnPropertyDescriptor(user, "name"));

Результат будет примерно таким:

{
  value: "Anna",
  writable: true,
  enumerable: true,
  configurable: true
}

Что возвращает метод

Если свойство существует и принадлежит самому объекту, метод вернёт объект-дескриптор.

Если такого собственного свойства нет, результатом будет undefined.

const user = { name: "Anna" };

console.log(Object.getOwnPropertyDescriptor(user, "name"));
// { value: "Anna", writable: true, enumerable: true, configurable: true }

console.log(Object.getOwnPropertyDescriptor(user, "age")); // undefined

Только собственные свойства

Это важный момент.

Метод не смотрит в прототип.

const base = { role: "user" };
const person = Object.create(base);

person.name = "Anna";

console.log(Object.getOwnPropertyDescriptor(person, "name"));
// дескриптор свойства name

console.log(Object.getOwnPropertyDescriptor(person, "role")); // undefined

Хотя person.role доступно, это свойство унаследовано, а не принадлежит самому объекту.

Обычное свойство: value, writable, enumerable, configurable

Для обычного свойства дескриптор обычно содержит такие поля:

  • value - само значение
  • writable - можно ли менять значение
  • enumerable - участвует ли свойство в перечислении
  • configurable - можно ли его перенастраивать или удалять

Пример:

const user = { name: "Anna" };

const descriptor = Object.getOwnPropertyDescriptor(user, "name");

console.log(descriptor.value);        // "Anna"
console.log(descriptor.writable);     // true
console.log(descriptor.enumerable);   // true
console.log(descriptor.configurable); // true

Неперечисляемое свойство

Через Object.defineProperty() можно создать свойство с другими настройками.

const user = {};

Object.defineProperty(user, "secret", {
  value: "123",
  enumerable: false,
});

console.log(Object.getOwnPropertyDescriptor(user, "secret"));

Здесь в дескрипторе будет видно, что enumerable равно false.

Геттеры и сеттеры

Если свойство устроено через getter/setter, дескриптор будет другим.

const user = {
  firstName: "Anna",
  lastName: "Smith",
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  },
};

console.log(Object.getOwnPropertyDescriptor(user, "fullName"));

В этом случае вместо value и writable в дескрипторе обычно будут:

  • get
  • set
  • enumerable
  • configurable

То есть метод помогает увидеть, что перед нами не обычное свойство, а accessor property.

Object.getOwnPropertyDescriptor() не меняет объект

Метод только читает информацию о свойстве и ничего не изменяет.

const user = { name: "Anna" };
const descriptor = Object.getOwnPropertyDescriptor(user, "name");

console.log(user);       // { name: "Anna" }
console.log(descriptor); // объект-дескриптор

Массивы тоже работают

Массив - это тоже объект, поэтому метод работает и с ним.

const arr = ["a", "b"];

console.log(Object.getOwnPropertyDescriptor(arr, "0"));
// { value: "a", writable: true, enumerable: true, configurable: true }

Интересный пример - length:

const arr = ["a", "b"];

console.log(Object.getOwnPropertyDescriptor(arr, "length"));

У length будут свои настройки, и это хороший способ увидеть, что свойство устроено не совсем как обычный индекс массива.

Символьные ключи

Метод умеет работать и с ключами-символами.

const id = Symbol("id");
const user = {
  [id]: 1,
};

console.log(Object.getOwnPropertyDescriptor(user, id));

Object.getOwnPropertyDescriptor() и Object.defineProperty()

Эти методы часто используют рядом:

  • Object.getOwnPropertyDescriptor() читает дескриптор
  • Object.defineProperty() создаёт или настраивает свойство
const user = { name: "Anna" };
const descriptor = Object.getOwnPropertyDescriptor(user, "name");

console.log(descriptor.enumerable); // true

То есть один метод помогает посмотреть настройки, а второй - изменить их.

Object.getOwnPropertyDescriptor() и Object.keys()

Object.keys() показывает только перечисляемые собственные ключи.

Object.getOwnPropertyDescriptor() позволяет понять, почему свойство попадает или не попадает в это перечисление.

const user = {};

Object.defineProperty(user, "secret", {
  value: "123",
  enumerable: false,
});

console.log(Object.keys(user)); // []
console.log(Object.getOwnPropertyDescriptor(user, "secret").enumerable); // false

Когда это полезно

Object.getOwnPropertyDescriptor() удобно использовать, когда:

  • нужно понять, почему свойство ведёт себя определённым образом
  • нужно проверить writable, enumerable или configurable
  • нужно разобраться, является ли свойство геттером/сеттером
  • вы работаете с Object.defineProperty()

Частые ошибки

Думать, что метод ищет свойства в прототипе

const base = { role: "user" };
const person = Object.create(base);

console.log(Object.getOwnPropertyDescriptor(person, "role")); // undefined

Метод смотрит только на собственные свойства объекта.

Ждать, что всегда будет поле value

const user = {
  get name() {
    return "Anna";
  },
};

console.log(Object.getOwnPropertyDescriptor(user, "name"));

Для геттера/сеттера структура дескриптора будет другой.

Путать значение свойства и дескриптор

const user = { name: "Anna" };

console.log(user.name); // "Anna"
console.log(Object.getOwnPropertyDescriptor(user, "name"));
// объект с настройками свойства

Метод возвращает не само значение, а описание свойства.

Быстрая памятка

  • Object.getOwnPropertyDescriptor() возвращает дескриптор собственного свойства
  • если свойства нет, результатом будет undefined
  • метод не смотрит в прототип
  • для обычных свойств важны value, writable, enumerable, configurable
  • для getter/setter дескриптор будет другим

Коротко

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