Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Object.freeze() у JavaScript». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`Object.freeze()` заморожує об'єкт: після виклику не можна перезаписати, додати чи видалити жодну властивість, а також змінити дескриптори `writable` і `configurable`.** Метод повертає той самий об'єкт, а не копію, а перевірити стан можна через `Object.isFrozen(obj)`. Важливо, що заморозка поверхнева (shallow): вкладені об'єкти лишаються змінюваними, тому для повної незмінності потрібен рекурсивний `deepFreeze()`. ```javascript const user = { name: 'Alice', age: 25 }; Object.freeze(user); user.name = 'Oleh'; // не змінить console.log(user); // { name: 'Alice', age: 25 } ``` **Ключове:** `Object.freeze()` робить об'єкт незмінним, але тільки на верхньому рівні.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`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()` рекурсія зациклюється і падає зі стеком.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.