Object.seal() in JavaScript
Object.seal() is a built-in JavaScript method that "seals" an object: it forbids adding or deleting properties but allows changing the values of the existing ones. It is similar to Object.freeze(), only softer, because it does not touch writability.
Theory
TL;DR
Object.seal(obj)forbids adding and deleting properties.- The values of existing properties can be changed.
- Technically it is
preventExtensions()plusconfigurable: falseon every own property. writablestays as it was, so writing works.- To check the state:
Object.isSealed(obj). - The effect is shallow: nested objects stay unsealed.
Quick example
const user = {
name: 'Alice',
age: 25
};
Object.seal(user);
user.age = 30; // the value can be changed
user.city = 'Kyiv'; // a new one cannot be added
delete user.name; // it cannot be deleted
console.log(user); // { name: 'Alice', age: 30 }After Object.seal():
- new properties cannot be added;
- existing ones cannot be deleted;
- but the values of existing properties can be changed.
Syntax and checking the state
Object.seal(obj)| Argument | Description |
|---|---|
obj | The object to "seal" |
The method returns the same object, now with the restrictions applied, so it is not a copy.
console.log(Object.isSealed(user)); // trueWhat happens under the hood
Object.seal(obj) does three things:
- Forbids adding new properties, that is, it performs
Object.preventExtensions(obj). - Sets
configurable: falseon every existing property, so they cannot be deleted and their descriptors cannot be changed. - Leaves
writableuntouched, which is exactly why values can still be changed.
This is easy to see on the descriptor:
const user = { name: 'Alice' };
Object.seal(user);
console.log(Object.getOwnPropertyDescriptor(user, 'name'));It prints:
{
value: 'Alice',
writable: true,
enumerable: true,
configurable: false
}You can see that configurable: false while writable stayed true.
Comparison with freeze and preventExtensions
| Method | Can change values | Can add | Can delete | Can change descriptors |
|---|---|---|---|---|
Object.preventExtensions() | Yes | No | Yes | Yes |
Object.seal() | Yes | No | No | No |
Object.freeze() | No | No | No | No |
So seal() is the middle ground between "flexible" and "strict". Note the relationship: every sealed object is automatically non-extensible, and every frozen object is automatically sealed, which is why Object.isSealed() also returns true for a frozen object.
Shallow seal
Object.seal() does not protect nested objects:
const user = {
name: 'Alice',
address: { city: 'Kyiv' }
};
Object.seal(user);
user.address.city = 'Lviv'; // allowed, the nested object is not sealed
user.city = 'Odesa'; // not allowed, that is a new property
console.log(user.address.city); // "Lviv"To "seal" the whole tree you need a deep seal with recursion:
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;
}Now everything can be "sealed", including nested structures. The !Object.isSealed(obj[key]) check protects against infinite recursion on circular references.
Summary table:
| What it does | Example | Behaviour |
|---|---|---|
| "Seals" the object | Object.seal(obj) | Forbids adding and deleting properties |
| Values can be changed | Yes | writable stays true |
| New properties can be added | No | the object becomes non-extensible |
| Properties can be deleted | No | configurable: false |
| Check | Object.isSealed(obj) | |
| Depth | Shallow, top level only |
Common mistakes
- Confusing
seal()withfreeze().seal()only fixes the set of keys; values can still be changed afterwards. - Expecting an error on
delete. In sloppy modedelete user.namesimply returnsfalseand does nothing, while under'use strict'it throws aTypeError. - Assuming the whole graph is protected. Nested objects and arrays stay fully mutable, you need
deepSeal(). - Counting on immutable state. If you need real immutability, that is
Object.freeze()or building a new object, notseal(). - Being surprised that
Object.isSealed()returnstruefor a frozen object. A frozen object is sealed by definition, that is not a bug.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.