Hiprup

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 mode

freeze: 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.

What is Object.freeze() vs Object.seal()? | Hiprup