Skip to main content

Object.seal() у JavaScript

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 на замороженому об'єкті. Заморожений об'єкт за визначенням також запечатаний, це не баг.

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

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

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