Коротка відповідь
juniorObject.defineProperty(obj, 'prop', {value: 42, writable: false, configurable: false}); – це створює властивість, яку не можна змінити. Якщо потрібна повна незмінність, використовуйте Object.freeze(obj).
Повне пояснення
Що це і навіщо
Object.definePropertyдозволяє задати атрибути властивості:writable,configurableта інші. Якщо встановитиwritable:false, значення не можна змінювати.
Ключові принципи
writable:false→ неможна присвоїти нове значення.configurable:false→ не можна видалити або змінити атрибути.enumerable:true/false→ чи буде властивість видимою в цикліfor…in.
Як це працює
- При виклику
Object.definePropertyстворюється «схема» для конкретної властивості. JavaScript‑рушій перевіряє атрибути перед кожною операцією присвоєння.
Практика і реалізація
const obj = {};
Object.defineProperty(obj, 'id', {
value: 123,
writable: false,
configurable: false,
enumerable: true
});
obj.id = 456; // нічого не зміниться, в консолі буде 123
Для повної незмінності об’єкта:
Object.freeze(obj); // блокує додавання, видалення та зміну всіх властивостей
Тестування
- У Jest можна перевірити:
expect(() => { obj.id = 456; }).not.toThrow();
expect(obj.id).toBe(123);
Оптимізація та edge‑cases
Object.freezeробить об’єкт «швидким» для читання, але не глибоко (не заморожує вкладені об’єкти). Для глибокої незмінності використовуйтеdeepFreezeабо бібліотеки типуimmutable.js.
Часті помилки
- Забуваєте встановити
configurable:false– властивість все одно можна видалити. - Використовуєте
constдля об’єкта, але це лише блокує переназначення змінної, а не властивостей. - Не заморожуєте вкладені об’єкти – вони залишаються змінними.
- Під час тестування не перевіряєте, що властивість дійсно неможна змінити.
- Використовуєте
Object.definePropertyбезenumerable:true, що приховає властивість у циклі. - Не враховуєте, що
Object.freezeне працює з геттерами/setтерами. - Не розумієте, що
writable:falseне блокує мутації через посилання (наприклад,obj.prop.push(1)для масиву). - Не перевіряєте, що
Object.freezeне працює в режимі strict без помилки.
Cheatsheet
Object.defineProperty(obj, 'key', {value: val, writable:false, configurable:false});Object.freeze(obj)– повна незмінність.- Для глибокої заморозки:
Object.keys(obj).forEach(k => Object.freeze(obj[k]));