What is Object.freeze() vs Object.seal()?
Both lock down an object, but to different degrees.
Object.freeze() — fully locks it: no adding, removing, or changing properties. Effectively read-only.
Object.seal() — prevents adding or removing properties, but existing values can still be changed.
Both are shallow: nested objects stay mutable unless you freeze them too.
// Object.freeze — fully immutable (shallow)
const config = Object.freeze({
api: 'https://api.example.com',
timeout: 5000,
nested: { debug: true }
});
config.api = 'new url'; // Silently fails (or TypeError in strict)
config.newProp = 'value'; // Silently fails
delete config.timeout; // Silently fails
config.nested.debug = false; // WORKS! Nested object not frozen
// Object.seal — can modify values, cannot add/remove
const user = Object.seal({
name: 'John',
age: 30
});
user.name = 'Jane'; // OK — modifying existing value
user.email = 'j@t.com'; // Fails — cannot add
delete user.age; // Fails — cannot delete
// Deep freeze utility
function deepFreeze(obj) {
Object.freeze(obj);
Object.values(obj).forEach(val => {
if (typeof val === 'object' && val !== null && !Object.isFrozen(val)) {
deepFreeze(val);
}
});
return obj;
}
const immutable = deepFreeze({ a: { b: { c: 1 } } });
// immutable.a.b.c = 2; // TypeError in strict modefreeze: cannot add, remove, or change any property. seal: cannot add or remove, but CAN change existing values. Both are shallow — nested objects remain mutable. deepFreeze recursively freezes all nested objects.
In strict mode, violations throw TypeError; in sloppy mode, they silently fail.
freeze = fully immutable (no changes), seal = no add/remove (but values can change). Both are SHALLOW — the nested object gotcha is always tested.
Show the deepFreeze utility for true immutability. Know Object.isFrozen/isSealed for checking.