Object.isSealed()
ES5+Returns true if an object is sealed — non-extensible with every own property non-configurable — regardless of whether values are still writable. Frozen objects always report true here as well, since freezing implies sealing.
Syntax
Object.isSealed(obj)Parameters
obj Object The object to check
Return Value
true if the object is sealed, otherwise false
Examples
const obj = { a: 1 };
console.log(Object.isSealed(obj));
Object.seal(obj);
console.log(Object.isSealed(obj)); 📌 When to Use
Use Object.isSealed() when code needs to confirm that an object's shape is locked before relying on that guarantee. Practical spots: validators that receive objects from plugin or user code and want to enforce fixed-schema contracts, debugging sessions where property additions mysteriously disappear (an isSealed check instantly explains the symptom), and diagnostic utilities that classify objects along the mutability spectrum by combining isExtensible, isSealed, and isFrozen. Because frozen implies sealed, always interpret results as a hierarchy: isSealed true plus isFrozen false pinpoints the middle state where structure is fixed but values still change — often exactly what you need to know before deciding whether an in-place update is possible or a replacement object is required. In state-management code, an isSealed assertion in development builds can enforce that reducers return objects of an agreed shape. Outside checks like these, you rarely need it in production hot paths; it is a verification and debugging tool more than an everyday operator.
⚠️ Common Mistakes
Treating isSealed true as "values cannot change" - sealed-but-not-frozen objects accept writes to existing properties. Authorization or caching logic that assumes value stability after an isSealed check is reading the wrong signal; it actually wants Object.isFrozen().
Checking the root and assuming the tree - like every mutability inspector, isSealed reports only on the object you pass it. A sealed wrapper around mutable nested objects still allows structural changes one level down, so audits of nested data need recursion.
Confusing isSealed with isFrozen - a frozen object is always sealed, but isSealed returns true for both sealed-only and frozen objects.
Assuming an empty object is not sealed - empty objects without properties are considered sealed by default.
✅ Best Practices
Build graceful fallbacks into shared utilities: when a merge helper detects Object.isSealed(target) is true, it can write only to keys that already exist and collect rejected keys into a warning report instead of throwing - keeping one generic function usable on both sealed DTOs and ordinary objects. Without the check, the same helper works in sloppy-mode development silence and explodes in production ES modules with a strict-mode TypeError, a class of environment-dependent bug that a single isSealed guard eliminates entirely.
Report all three flags together when debugging: logging { extensible: Object.isExtensible(obj), sealed: Object.isSealed(obj), frozen: Object.isFrozen(obj) } identifies the exact restriction level at a glance instead of guessing from one boolean at a time.
Gate development-only shape assertions behind an environment flag: cheap isSealed checks in dev builds catch schema violations early, while production builds skip the verification work entirely and pay nothing.
Use in combination with isFrozen to determine the exact mutability level: sealed but not frozen means values can change.
Create a utility to check object mutability state: { sealed: Object.isSealed(obj), frozen: Object.isFrozen(obj), extensible: Object.isExtensible(obj) }
⚡ Performance Notes
Object.isSealed() checks extensibility first, then scans own properties until it finds one that is still configurable, so the worst case is O(n) but it short-circuits early on unsealed objects — an extensible object answers immediately without touching properties at all. For the small objects that typically get sealed (sessions, configs, DTOs) the cost is unmeasurable, and using it in guard clauses or assertions is free for practical purposes. As with the other inspectors, avoid redundant calls in tight loops when the answer cannot change between iterations; the result for a given object only changes when someone seals it, which normally happens exactly once at creation. Diagnostic sweeps that walk entire object graphs calling isSealed recursively belong in tests and dev tooling rather than per-request production code.
🌍 Real World Example
Object Mutability Inspector
This mutability inspector combines Object.isSealed() with isFrozen and isExtensible to classify any object into one of four states — mutable, non-extensible, sealed, or frozen — and returns a readable report with a property count. Running it against a normal, a sealed, and a frozen object shows how the flags nest: the frozen object reports sealed as well, while the sealed one keeps writable values. Inspectors like this are handy in debugging sessions, code reviews of state-management layers, and educational demos alike.
function inspectMutability(obj, name = 'Object') {
const isSealed = Object.isSealed(obj);
const isFrozen = Object.isFrozen(obj);
const isExtensible = Object.isExtensible(obj);
let status;
if (isFrozen) {
status = 'FROZEN (completely immutable)';
} else if (isSealed) {
status = 'SEALED (fixed structure, mutable values)';
} else if (!isExtensible) {
status = 'NON-EXTENSIBLE (no new props, can delete/modify)';
} else {
status = 'MUTABLE (fully changeable)';
}
return {
name,
isSealed,
isFrozen,
isExtensible,
status,
propertyCount: Object.keys(obj).length
};
}
// Test different object states
const normal = { a: 1 };
const sealed = Object.seal({ b: 2 });
const frozen = Object.freeze({ c: 3 });
console.log(inspectMutability(normal, 'Normal'));
// { name: 'Normal', isSealed: false, isFrozen: false, isExtensible: true, status: 'MUTABLE', propertyCount: 1 }
console.log(inspectMutability(sealed, 'Sealed'));
// { name: 'Sealed', isSealed: true, isFrozen: false, isExtensible: false, status: 'SEALED', propertyCount: 1 }
console.log(inspectMutability(frozen, 'Frozen'));
// { name: 'Frozen', isSealed: true, isFrozen: true, isExtensible: false, status: 'FROZEN', propertyCount: 1 }