Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Object.seal() у JavaScript». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`Object.seal()` «запечатує» об'єкт: додавати нові властивості та видаляти наявні не можна, але змінювати значення вже наявних властивостей дозволено.** Під капотом він викликає `Object.preventExtensions()` і виставляє всім власним властивостям `configurable: false`, залишаючи `writable: true`. Перевірка стану, `Object.isSealed(obj)`; дія поверхнева, тож вкладені об'єкти лишаються незапечатаними. ```javascript const user = { name: 'Alice', age: 25 }; Object.seal(user); user.age = 30; // можна змінити значення user.city = 'Kyiv'; // не можна додати нове delete user.name; // не можна видалити console.log(user); // { name: 'Alice', age: 30 } ``` **Ключове:** `seal()` фіксує набір ключів, а не значення; це проміжний варіант між `preventExtensions()` і `freeze()`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`Object.seal()` це вбудований метод JavaScript, який «запечатує» об'єкт: він забороняє додавати або видаляти властивості, але дозволяє змінювати значення наявних.** Він схожий на `Object.freeze()`, тільки м’якший, бо не чіпає можливість запису. ## Теорія ### TL;DR - `Object.seal(obj)` забороняє **додавати** і **видаляти** властивості. - Значення наявних властивостей **змінювати можна**. - Технічно це `preventExtensions()` плюс `configurable: false` на кожній власній властивості. - `writable` лишається як було, тому запис працює. - Перевірка стану: `Object.isSealed(obj)`. - Дія **поверхнева**: вкладені об'єкти лишаються незапечатаними. ### Швидкий приклад ```javascript const user = { name: 'Alice', age: 25 }; Object.seal(user); user.age = 30; // можна змінити значення user.city = 'Kyiv'; // не можна додати нове delete user.name; // не можна видалити console.log(user); // { name: 'Alice', age: 30 } ``` Після `Object.seal()`: - не можна додавати нові властивості; - не можна видаляти наявні; - але **можна міняти значення** вже наявних властивостей. ### Синтаксис і перевірка стану ```javascript Object.seal(obj) ``` | Аргумент | Опис | | --- | --- | | `obj` | Об'єкт, який потрібно «запечатати» | Метод повертає той самий об'єкт, але вже з обмеженнями, тобто це не копія. ```javascript console.log(Object.isSealed(user)); // true ``` ### Що відбувається «під капотом» `Object.seal(obj)` робить три речі: 1. **Забороняє додавання нових властивостей**, тобто виконує `Object.preventExtensions(obj)`. 2. Для всіх наявних властивостей виставляє `configurable: false`, тож їх не можна видалити і не можна змінити дескриптор. 3. Залишає `writable` без змін, саме тому значення можна міняти. Це добре видно на дескрипторі: ```javascript const user = { name: 'Alice' }; Object.seal(user); console.log(Object.getOwnPropertyDescriptor(user, 'name')); ``` Виведе: ```javascript { value: 'Alice', writable: true, enumerable: true, configurable: false } ``` Видно, що `configurable: false`, а `writable` лишилося `true`. ### Порівняння з freeze і preventExtensions | Метод | Можна міняти значення | Можна додавати | Можна видаляти | Можна міняти дескриптори | | --- | --- | --- | --- | --- | | `Object.preventExtensions()` | Так | Ні | Так | Так | | `Object.seal()` | Так | Ні | Ні | Ні | | `Object.freeze()` | Ні | Ні | Ні | Ні | Тобто `seal()` це проміжний варіант між «гнучким» і «жорстким». Зверніть увагу на зв'язок: кожен запечатаний об'єкт автоматично нерозширюваний, а кожен заморожений об'єкт автоматично запечатаний, тому `Object.isSealed()` повертає `true` і для замороженого об'єкта. ### Поверхнева дія (shallow seal) `Object.seal()` **не захищає вкладені об'єкти**: ```javascript const user = { name: 'Alice', address: { city: 'Kyiv' } }; Object.seal(user); user.address.city = 'Lviv'; // можна, вкладений об'єкт не запечатано user.city = 'Odesa'; // не можна, це нова властивість console.log(user.address.city); // "Lviv" ``` Щоб «запечатати» все дерево, потрібна **глибока запечатка** рекурсією: ```javascript function deepSeal(obj) { Object.seal(obj); for (const key in obj) { if (typeof obj[key] === 'object' && obj[key] !== null && !Object.isSealed(obj[key])) { deepSeal(obj[key]); } } return obj; } ``` Тепер можна «запечатати» все, включно з вкладеними структурами. Перевірка `!Object.isSealed(obj[key])` захищає від нескінченної рекурсії на циклічних посиланнях. Підсумкова таблиця: | Що робить | Приклад | Поведінка | | --- | --- | --- | | «Запечатує» об'єкт | `Object.seal(obj)` | Забороняє додавання і видалення властивостей | | Можна змінювати значення | Так | `writable` лишається `true` | | Можна додавати нові властивості | Ні | об'єкт стає нерозширюваним | | Можна видаляти властивості | Ні | `configurable: false` | | Перевірка | `Object.isSealed(obj)` | | | Глибина | Поверхнево, тільки верхній рівень | | ### Типові помилки - **Плутати `seal()` із `freeze()`.** `seal()` фіксує лише набір ключів; значення після нього спокійно змінюються. - **Чекати на помилку при `delete`.** У нестрогому режимі `delete user.name` просто поверне `false` і нічого не зробить, а в `'use strict'` кине `TypeError`. - **Вважати, що захищено весь граф.** Вкладені об'єкти та масиви лишаються повністю змінюваними, потрібен `deepSeal()`. - **Розраховувати на незмінність стану.** Якщо потрібна справжня immutability, це `Object.freeze()` або створення нового об'єкта, а не `seal()`. - **Дивуватися, що `Object.isSealed()` дає `true` на замороженому об'єкті.** Заморожений об'єкт за визначенням також запечатаний, це не баг.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.