JavaScript Objects: References, Cloning, and Immutability (Deep vs Shallow)

A deep interview-ready guide to object references in JavaScript: shallow vs deep copies, structuredClone, JSON pitfalls, immutability patterns, and common bugs.

F

Frontend Interview Team

February 08, 2026

~20 min
JavaScript Objects: References, Cloning, and Immutability (Deep vs Shallow)

Objects in JS are reference types. Most real-world frontend bugs with state come from misunderstanding references.

This post gives you the mental model + the practical cloning tools.

30‑second interview answer

Objects are reference types, so assignments copy the reference, not the value. A shallow copy copies only the top level; nested objects are still shared. For deep copies, prefer structuredClone when available, or carefully clone via libraries—JSON cloning loses types (Dates, Maps) and breaks functions/undefined. Immutability is crucial in React state to avoid subtle bugs.

Key points

  • Shallow copy ≠ deep copy.
  • Spread {...obj} is shallow.
  • structuredClone is safest general-purpose deep clone.
  • JSON cloning has many pitfalls.

1) Primitives vs objects (core concept)

Primitives (copied by value):

  • string, number, boolean, null, undefined, symbol, bigint

Objects (copied by reference):

  • objects, arrays, functions, dates, maps, sets
let a = { x: 1 };
let b = a;
 
b.x = 2;
console.log(a.x); // 2

Because a and b point to the same object.


2) Shallow copy vs deep copy

Shallow copy

Copies only the top-level structure. Nested objects are still shared references.

const obj = { a: 1, nested: { n: 1 } };
const copy = { ...obj };
 
copy.nested.n = 99;
console.log(obj.nested.n); // 99 (still shared!)

Shallow copy tools:

  • { ...obj }
  • Object.assign({}, obj)
  • arr.slice() / [...arr]

Deep copy

Copies nested objects too.


3) Best modern option: structuredClone

If your runtime supports it (modern browsers + newer Node):

const deep = structuredClone(obj);

Pros:

  • handles many built-in types
  • avoids many JSON pitfalls

Cons:

  • not supported in very old environments
  • cannot clone functions

4) JSON cloning (common, but has pitfalls)

const deep = JSON.parse(JSON.stringify(obj));

Pitfalls:

  • drops undefined, functions, symbols
  • converts Date to string
  • fails on circular references
  • loses Map/Set

Use JSON clone only for simple data.


5) Circular references

const a = {};
a.self = a;
 
JSON.stringify(a); // TypeError

If you expect cycles, use structuredClone or a custom clone.


6) Immutability patterns (frontend interview + React)

Why immutability matters:

  • predictable updates
  • easier debugging
  • change detection (React, Redux) relies on new references

A) Update nested object immutably

const state = { user: { name: 'Rajesh', address: { city: 'Kharar' } } };
 
const next = {
  ...state,
  user: {
    ...state.user,
    address: {
      ...state.user.address,
      city: 'Toronto'
    }
  }
};

B) Update arrays immutably

const items = [1, 2, 3];
const next = items.map((x) => (x === 2 ? 99 : x));

7) When mutation is fine

Mutation is not “evil”. It’s about controlling side effects.

Mutation is okay when:

  • object is local and not shared
  • you control the lifecycle
  • you’re doing performance-critical work in a tight loop

But for state management, prefer immutability.


8) Interview Q&A

Q: Why is [] === [] false?

  • different references.

Q: Is {...obj} a deep copy?

  • No, it’s shallow.

Q: Best way to deep copy in JS?

  • structuredClone when available; otherwise careful custom clone.

Q: Why do React updates require creating new objects?

  • React often uses shallow comparison of references.

Summary checklist

  • I can explain reference vs value.
  • I can explain shallow vs deep copy.
  • I know structuredClone is preferred for deep copy.
  • I can list JSON-clone pitfalls.

Summary

  • Objects/arrays are references.
  • Spread/Object.assign create shallow copies.
  • Use structuredClone for deep copy when possible.
  • JSON cloning has many pitfalls.
  • Immutability patterns are essential for frontend apps.