0Pricing
JavaScript Academy · Lesson

Shallow vs Deep Freezing

Understand how far freezing reaches.

Shallow vs Deep Freezing is a free JavaScript Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Freeze Is Shallow

Object.freeze only locks the top level of an object. Any nested object or array it references remains fully mutable.

This surprises many developers and causes subtle bugs.

Proving the Shallow Limit

Freeze an object with a nested object. The top level is locked, but the nested object can still change.

const user = Object.freeze({
  name: 'Ada',
  address: { city: 'London' }
});

user.name = 'Grace';
user.address.city = 'Paris';

console.log(user.name);
console.log(user.address.city);

Nested Arrays Too

Arrays inside a frozen object are also unprotected. You can push, pop, and reassign their elements.

const state = Object.freeze({ tags: ['a', 'b'] });

state.tags.push('c');
state.tags[0] = 'X';

console.log(state.tags);

isFrozen Confirms It

The nested object reports isFrozen as false, confirming the freeze did not reach inside.

const obj = Object.freeze({ inner: { v: 1 } });

console.log(Object.isFrozen(obj));
console.log(Object.isFrozen(obj.inner));

Writing deepFreeze

To lock everything, recurse: freeze the object, then freeze each nested object property. This is deep freezing.

function deepFreeze(obj) {
  for (const key of Object.keys(obj)) {
    const value = obj[key];
    if (value && typeof value === 'object') {
      deepFreeze(value);
    }
  }
  return Object.freeze(obj);
}

const data = deepFreeze({ a: { b: { c: 1 } } });
data.a.b.c = 999;
console.log(data.a.b.c);

deepFreeze on Arrays

Arrays are objects too, so the same recursion freezes them. Pushes and element writes are then blocked at every depth.

function deepFreeze(obj) {
  for (const key of Object.keys(obj)) {
    const value = obj[key];
    if (value && typeof value === 'object') deepFreeze(value);
  }
  return Object.freeze(obj);
}

const state = deepFreeze({ list: [1, 2, 3] });
state.list.push(4);
state.list[0] = 99;
console.log(state.list);

Verifying Deep Freeze

After deep freezing, every nested object reports isFrozen as true.

function deepFreeze(obj) {
  for (const key of Object.keys(obj)) {
    const v = obj[key];
    if (v && typeof v === 'object') deepFreeze(v);
  }
  return Object.freeze(obj);
}

const o = deepFreeze({ a: { b: 1 } });
console.log(Object.isFrozen(o));
console.log(Object.isFrozen(o.a));

Guarding Against Cycles

If an object references itself, naive recursion loops forever. Skip already-frozen objects to stay safe.

function deepFreeze(obj) {
  if (Object.isFrozen(obj)) return obj;
  for (const key of Object.keys(obj)) {
    const v = obj[key];
    if (v && typeof v === 'object') deepFreeze(v);
  }
  return Object.freeze(obj);
}

const a = { name: 'a' };
a.self = a;
deepFreeze(a);
console.log(Object.isFrozen(a.self));

Cost of Deep Freezing

Deep freezing visits every nested value, which costs time and memory for large structures. Freeze only what truly needs protection, such as shared config or constants.

function deepFreeze(obj) {
  if (Object.isFrozen(obj)) return obj;
  Object.keys(obj).forEach(k => {
    const v = obj[k];
    if (v && typeof v === 'object') deepFreeze(v);
  });
  return Object.freeze(obj);
}

const small = deepFreeze({ a: 1, b: { c: 2 } });
console.log('frozen deeply:', Object.isFrozen(small.b));

When Shallow Is Enough

If an object only holds primitives, a shallow Object.freeze already protects it fully. Deep freezing matters only when there are nested objects or arrays.

const flat = Object.freeze({ a: 1, b: 'two', c: true });
flat.a = 100;
console.log(flat.a);
console.log(Object.isFrozen(flat));

Why It Matters

Understanding shallow vs deep freezing prevents the trap of thinking a frozen object is fully immutable. For nested data, recurse. As an alternative to mutation, the next lessons cover immutable update patterns that copy instead of freeze.

const config = Object.freeze({ db: { host: 'local' } });
config.db.host = 'changed';
console.log('shallow freeze leaked:', config.db.host);

Quick Check

After Object.freeze({ a: { b: 1 } }), can you change the nested b?

Recap: Shallow vs Deep Freeze

You learned the depth limit of freezing:

  • Object.freeze is shallow; nested objects and arrays stay mutable.
  • deepFreeze recurses to lock every level.
  • Guard against cycles by skipping already-frozen objects.
  • Deep freezing has a cost, so freeze only what needs protection.

Frequently asked questions

Is the “Shallow vs Deep Freezing” lesson free?

Yes — the full text of “Shallow vs Deep Freezing” is free to read here on the web, and the JavaScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the JavaScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Shallow vs Deep Freezing”?

Understand how far freezing reaches. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start JavaScript Academy?

No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Shallow vs Deep Freezing” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this JavaScript Academy lesson?

Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Object.freeze and seal
  2. Shallow vs Deep Freezing
  3. Immutable Update Patterns
  4. structuredClone for Deep Copies
← Back to JavaScript Academy