Skip to main content

Object.freeze() у JavaScript

Object.freeze() це вбудований метод JavaScript, який «заморожує» об'єкт і робить його повністю незмінним: властивості не можна змінити, видалити або додати. Метод повертає той самий об'єкт, а не його копію, і діє лише на верхній рівень структури.

Теорія

TL;DR

  • Object.freeze(obj) робить об'єкт незмінним і повертає той самий об'єкт.
  • Не можна перезаписати, додати або видалити властивості.
  • Не можна змінити дескриптори configurable і writable.
  • Перевірка стану: Object.isFrozen(obj).
  • Заморозка поверхнева (shallow): вкладені об'єкти лишаються змінюваними.
  • Object.seal() забороняє додавання і видалення, але дозволяє змінювати значення; Object.preventExtensions() забороняє лише додавання нових властивостей.

Швидкий приклад

javascript
const user = { name: 'Alice', age: 25 }; Object.freeze(user); user.name = 'Oleh'; // не змінить user.city = 'Kyiv'; // не можна додати нове delete user.age; // не можна видалити console.log(user); // { name: 'Alice', age: 25 }

Синтаксис і перевірка стану

javascript
Object.freeze(obj)
АргументОпис
objОб'єкт, який потрібно «заморозити»

Метод повертає той самий об'єкт, але вже із замороженими властивостями, тому запис const frozen = Object.freeze(user) дає не копію, а друге ім'я для user.

Після Object.freeze() об'єкт стає незмінним:

  • властивості не можна перезаписати;
  • не можна видалити або додати нові;
  • не можна поміняти configurable або writable.

Перевірити стан можна окремим методом:

javascript
console.log(Object.isFrozen(user)); // true

Варто пам’ятати про режим виконання: у звичайному (нестрогому) коді спроба запису просто мовчки ігнорується, а в 'use strict' або всередині ES-модуля вона кидає TypeError. Саме тому баг легко не помітити в старому скрипті і одразу побачити в сучасному модулі.

Заморозка поверхнева (shallow)

Якщо всередині є вкладені об'єкти, вони лишаються змінюваними:

javascript
const user = { name: 'Alice', address: { city: 'Kyiv' } }; Object.freeze(user); user.address.city = 'Lviv'; // працює console.log(user.address.city); // "Lviv"

Тобто Object.freeze() захищає тільки верхній рівень. Заморожено саме посилання на address: замінити його іншим об'єктом не можна, а от змінити щось усередині того самого об'єкта, будь ласка. Для «глибокої» заморозки потрібно заморожувати рекурсивно.

Глибока заморозка (deep freeze)

javascript
function deepFreeze(obj) { Object.freeze(obj); for (const key in obj) { if (typeof obj[key] === 'object' && obj[key] !== null && !Object.isFrozen(obj[key])) { deepFreeze(obj[key]); } } return obj; } const user = { name: 'Alice', address: { city: 'Kyiv' } }; deepFreeze(user); user.address.city = 'Lviv'; // не змінить console.log(user.address.city); // "Kyiv"

Тепер об'єкт і весь його вміст повністю «заморожені». Перевірка !Object.isFrozen(obj[key]) потрібна не лише для швидкості: без неї циклічне посилання (a.self = a) призвело б до нескінченної рекурсії.

freeze, seal і preventExtensions

МетодЩо робитьМожна міняти значенняМожна додавати або видаляти властивості
Object.freeze()Повністю заморожуєНіНі
Object.seal()Забороняє додавання і видалення, але дозволяє міняти значенняТакНі
Object.preventExtensions()Забороняє додавання нових властивостейТакДодавати не можна, старі видаляти можна

Приклад freeze проти seal:

javascript
const user = { name: 'Alice' }; Object.seal(user); user.name = 'Oleh'; // можна delete user.name; // не можна Object.freeze(user); user.name = 'Max'; // не можна

Підсумкова таблиця:

ВластивістьПоведінка
Object.freeze()робить об'єкт повністю незмінним
Забороненододавати, видаляти або змінювати властивості
Працює поверхневовкладені об'єкти лишаються змінюваними
ПеревіркаObject.isFrozen(obj)

Типові помилки

  • Вважати, що заморожено весь граф об'єктів. Object.freeze() захищає лише верхній рівень; масив усередині замороженого об'єкта спокійно приймає push().
  • Розраховувати на помилку при записі. У нестрогому режимі присвоєння до замороженої властивості мовчки нічого не робить, тому баг живе непоміченим до переходу на модулі або 'use strict'.
  • Плутати freeze і seal. Object.seal() фіксує лише набір ключів, значення наявних властивостей змінювати можна.
  • Думати, що метод повертає копію. Він повертає той самий об'єкт, тож усі старі посилання теж стають замороженими.
  • Морозити об'єкт, який потім треба оновлювати. Для стану додатка краще створювати новий об'єкт ({ ...state, city: 'Lviv' }), а не намагатися мутувати заморожений.
  • Забувати про циклічні посилання в deepFreeze(). Без перевірки Object.isFrozen() рекурсія зациклюється і падає зі стеком.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.