JS Advanced

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

Понять, как свойства объекта определяются через writable, enumerable, configurable, value, get/set, и как это контролировать.

Продвинутый (Advanced)
Нужно знать:Объекты

Кратко

Каждое свойство объекта имеет дескриптор: value (значение), writable (можно ли менять), enumerable (видно ли в циклах), configurable (можно ли удалить/изменить). Object.defineProperty() задаёт свойство с нужными дескрипторами.


Подробно

Object.getOwnPropertyDescriptor: const obj = { name: 'Анна' }; console.log(Object.getOwnPropertyDescriptor(obj, 'name')); // { value: 'Анна', writable: true, enumerable: true, configurable: true }

Object.defineProperty: const user = {}; Object.defineProperty(user, 'name', { value: 'Анна', writable: false, // нельзя изменить enumerable: true, // видно в for...in configurable: false // нельзя удалить });

user.name = 'Борис'; // TypeError (в strict mode) // неявное присваивание игнорируется

Getter/Setter: let temperature = 20; const weather = { get celsius() { return temperature; }, set celsius(value) { temperature = value; console.log(Updated: ${value}°C); } };

weather.celsius = 25; // 'Updated: 25°C' console.log(weather.celsius); // 25

Определяем все свойства сразу: Object.defineProperties(user, { name: { value: 'Анна', writable: true }, age: { value: 25, writable: false } });


Ментальная модель

Дескриптор — как характеристика товара на этикетке. value — цена. writable — можно ли менять цену. enumerable — виден ли товар в витрине. configurable — можно ли снять товар с продажи.


Примеры

**Самый простой:**

javascript
const obj = {};

Object.defineProperty(obj, 'secret', {
  value: 42,
  writable: false,
  enumerable: false,
  configurable: false
});

console.log(obj.secret); // 42
obj.secret = 100; // не работает (не в strict mode)
console.log(Object.keys(obj)); // [] — secret не enumerable

Скрытое неизменяемое свойство.

**Простой:**

javascript
// Getter/Setter
class Temperature {
  #celsius = 0;

  get fahrenheit() {
    return this.#celsius * 9/5 + 32;
  }

  set fahrenheit(f) {
    this.#celsius = (f - 32) * 5/9;
  }

  get celsius() {
    return this.#celsius;
  }

  set celsius(c) {
    this.#celsius = c;
  }
}

const temp = new Temperature();
temp.celsius = 100;
console.log(temp.fahrenheit); // 212

Getter/Setter для конвертации температуры.

**Реальный пример:**

javascript
// Реактивное свойство
function reactiveProperty(obj, key, initialValue) {
  let value = initialValue;

  Object.defineProperty(obj, key, {
    get() {
      console.log(`GET ${key}`);
      return value;
    },
    set(newValue) {
      console.log(`SET ${key} = ${newValue}`);
      value = newValue;
    },
    enumerable: true,
    configurable: true
  });
}

const state = {};
reactiveProperty(state, 'count', 0);

state.count;     // GET count
state.count = 5; // SET count = 5

Реактивные свойства через defineProperty.


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

**Неправильно:** Путать writable и configurable

**Почему:** writable — можно ли менять значение. configurable — можно ли удалить/изменить дескриптор.

**Правильно:** writable = значение защищено. configurable = сама роль защищена.

**Неправильно:** Думать, что configurable: false нельзя изменить

**Почему:** configurable: false запрещает удаление и изменение дескриптора, но writable: true позволяет менять значение.

**Правильно:** configurable: false ≠ readonly. Значение можно менять если writable: true.


Важно запомнить

  • writable — можно ли менять значение
  • enumerable — видно ли в циклах и Object.keys
  • configurable — можно ли удалить/изменить дескриптор
  • get/set — вместо value для вычисляемых свойств
  • Object.defineProperty для точного контроля

Связь

Назад: Вы знаете объекты (J11). Дескрипторы дают низкоуровневый контроль над свойствами.

Вперёд: Следующий урок (JV16) — каррирование — преобразование функций для частичного применения.

Материалы курса JS Advanced — PROlab Academy.