Назад к вопросам
Middle+
138
questionbank

Что ты знаешь о дескрипторах?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Дескрипторы в JavaScript — это объекты, которые описывают различные свойства свойства объекта, такие как его значение (value), возможность записи (writable), возможность перечисления (enumerable) и возможность конфигурации (configurable). Также есть дескрипторы с геттерами и сеттерами.

Существует два типа дескрипторов:

  • Дескрипторы данных: Содержат значение свойства.

    • value: Значение свойства. Может быть любым валидным типом данных.
    • writable: Логическое значение. Если true, значение свойства можно изменить (obj.prop = newValue). По умолчанию false для accessor-свойств и true для data-свойств, созданных обычным присваиванием.
    • enumerable: Логическое значение. Если true, свойство будет видно при итерации по свойствам объекта (например, в цикле for...in или при использовании Object.keys()). По умолчанию false для свойств, добавленных Object.defineProperty, и true для свойств, созданных обычным присваиванием.
    • configurable: Логическое значение. Если true, характеристики дескриптора (кроме value и writable при их изменении с данными на аксессоры) можно изменять, а само свойство удалять. По умолчанию false для свойств, добавленных Object.defineProperty (кроме value), и true для свойств, созданных обычным присваиванием. Once configured as non-configurable, cannot be changed back. You can decrease writability from true to false, but not vice versa on a non-configurable getter/setter.
  • Дескрипторы аксессоров: Определяют функции, которые будут вызываться при получении (getter) или установке (setter) значения свойства.

    • get: Функция, вызываемая при чтении свойства. Результат этой функции становится значением свойства. Не принимает аргументов.
    • set: Функция, вызываемая при записи в свойство. Принимает одно аргумент — новое устанавливаемое значение.
    • enumerable: Логическое значение (аналогично data-дескрипторам).
    • configurable: Логическое значение (аналогично data-дескрипторам).

Дескрипторы нельзя смешивать: у свойства либо есть value и writable, либо get и set.

Дескрипторы используются для управления свойствами объекта на более низком уровне, чем обычное присваивание, в частности через методы Object.defineProperty(), Object.defineProperties(), Object.getOwnPropertyDescriptor(), Object.getOwnPropertyDescriptors(), Object.create().

Пример создания свойства с дескриптором данных:

// Создаем пустой объект
const obj = {};

// Определяем свойство 'name' с дескриптором данных
Object.defineProperty(obj, 'name', {
  value: 'Alice',
  writable: false, // Свойство нельзя изменить
  enumerable: true, // Свойство будет перечисляемым
  configurable: false // Характеристики свойства нельзя изменить, свойство нельзя удалить
});

console.log(obj.name); // Выведет: Alice

// Попытка изменить свойство (будет проигнорирована в строгом режиме или выбросит ошибку)
obj.name = 'Bob';
console.log(obj.name); // Выведет: Alice

// Попытка удалить свойство (будет проигнорирована или выбросит ошибку)
delete obj.name;
console.log(obj.name); // Выведет: Alice

Пример создания свойства с дескриптором аксессоров:

// Создаем объект с приватной переменной
const user = {
  _firstName: 'John', // Приватная переменная по соглашению
  _lastName: 'Doe'
};

// Определяем свойство 'fullName' с дескриптором аксессоров
Object.defineProperty(user, 'fullName', {
  get() {
    // Геттер: возвращает полное имя
    return `${this._firstName} ${this._lastName}`;
  },
  set(value) {
    // Сеттер: разбивает полное имя на части и обновляет приватные переменные
    const parts = value.split(' ');
    this._firstName = parts[0];
    this._lastName = parts[1];
  },
  enumerable: true, // Свойство будет перечисляемым
  configurable: true // Характеристики свойства можно изменить, свойство можно удалить
});

console.log(user.fullName); // Выведет: John Doe

user.fullName = 'Peter Pan';
console.log(user._firstName); // Выведет: Peter
console.log(user._lastName); // Выведет: Pan
console.log(user.fullName); // Выведет: Peter Pan

Использование дескрипторов позволяет создавать иммутабельные свойства, свойства с ленивым вычислением, свойства с контролем доступа (геттеры/сеттеры) и более гибко управлять поведением объектов.