JavaScript Academy · Lesson

Shallow vs Deep Freezing

Understand how far freezing reaches.

Lesson 2 of 413 steps

Shallow vs Deep Freezing is a free JavaScript Academy lesson on CoddyKit. This is lesson 2 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, and your progress syncs across the web and the CoddyKit app. The JavaScript Academy course includes 4 lessons in total.

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.
Free to start

Learn JavaScript with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
59
Lessons
200

Frequently Asked Questions

Is the “Shallow vs Deep Freezing” lesson free?

Yes — any 3 lessons of the JavaScript Academy learning path, including “Shallow vs Deep Freezing”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The JavaScript Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 4.

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