Objectsintermediate
Object.freeze, seal, and Immutability Patterns
Built-in methods for restricting how much an object can be changed, and why true deep immutability requires more than a single call.
Three levels of restriction, all shallow.
Object.freeze is like laminating the cover page of a document — the cover itself can't be altered anymore, but if the cover references a separate folder full of loose pages (a nested object), those loose pages are still completely free to be rewritten unless you laminate every single page inside that folder too.
Key Concepts
1
Object.preventExtensions(o) no new properties
Object.seal(o) no new, no delete; existing
ones still writable
Object.freeze(o) no new, no delete, no change2
And freeze only reaches one level.
const o = Object.freeze({ a: 1, nested: { b: 2 } });freeze
3
o.a = 99; // ignored (throws in strict mode)
o.nested.b = 99; // works -- nested is a different object4
That is the thing to know. freeze freezes the object, not the graph.
freeze
5
A deep freeze is recursive.
function deepFreeze(o) {
Object.values(o).forEach(v => {
if (v && typeof v === 'object') deepFreeze(v);
});
return Object.freeze(o);
}6
Watch for cycles, and note that freezing a large structure costs time and cannot be undone.
7
Silent versus loud failure.
const o = Object.freeze({ a: 1 });
o.a = 2; // sloppy: ignored. strict: TypeError8
In a module or a class you are already in strict mode, so it throws — which is what you want, since a silent
no-op is a bug you find much later.
9
Checking.
Object.isFrozen(o)
Object.isSealed(o)
Object.isExtensible(o)10
The pattern used in practice is not freezing — it is not mutating.
// instead of mutating
state.items.push(item);11
// produce a new value
const next = { ...state, items: [...state.items, item] };12
Redux, React state and every immutable update follow this. Freezing is a way to enforce it during
development; the discipline is what actually delivers the benefit.
13
The new non-mutating array methods exist for the same reason:
14
arr.toSorted() instead of arr.sort()
arr.toReversed() instead of arr.reverse()
arr.with(i, v) instead of arr[i] = v15
When freezing is worth the cost. Configuration objects and constants that must not be edited, and
development-mode checks in a library. Freezing application state on every update is expensive and rarely
justified — Object.freeze is not free.
16
What the interviewer is probing.1. "What is the difference between freeze and seal?" Probing: the two levels. Stalls: "The
same." Moves up: seal prevents adding or removing properties but allows changing existing ones;
freeze also makes them read-only.
17
2. "Is Object.freeze deep?" Probing: the depth. Stalls: "Yes." Moves up: no — it is
shallow, so nested objects stay mutable; a deep freeze means recursing.
18
3. "What happens writing to a frozen property?" Probing: the silent failure. Stalls: "It
throws." Moves up: it fails silently in sloppy mode and throws only in strict mode, which is why
the bug is easy to miss.
19
4. "How do you update state immutably?" Probing: the pattern. Stalls: "Mutate a copy."
Moves up: spread the level being changed and reuse the rest by reference, so unchanged branches
keep their identity for comparison.