ESC

Type to search the knowledge base.

Deep vs Shallow Copy

Shallow copy shares nested refs; deep copy clones the graph — spread, structuredClone, JSON limits, and React state implications.

beginner3 min read
  • javascript
  • deep-copy
  • shallow-copy
  • immutability

Assigning an object copies the reference, not the value. A shallow copy duplicates the top level only — nested objects still shared. A deep copy clones the whole reachable graph (within limits). Most production bugs are shallow-when-you-needed-deep, or deep-when-shallow-was-enough and expensive.

Same reference

const a = { user: { name: 'Ada' } };
const b = a;
b.user.name = 'Grace';
a.user.name; // 'Grace' — same object

Shallow copy

const original = {
  n: 1,
  nested: { ok: true },
  tags: ['js'],
};

const spread = { ...original };
const assign = Object.assign({}, original);
const fromEntries = Object.fromEntries(Object.entries(original));
const arrCopy = original.tags.slice(); // or [...tags]

spread.n = 2;
original.n; // 1 — top-level primitive copied

spread.nested.ok = false;
original.nested.ok; // false — nested shared

Arrays: [...arr], arr.slice(), Array.from(arr) are shallow.

Deep copy options

structuredClone (prefer)

const deep = structuredClone(original);
deep.nested.ok = true;
original.nested.ok; // false — independent

// supports: Date, Map, Set, ArrayBuffer, cyclic refs (in modern engines)
const withCycle = { a: 1 };
withCycle.self = withCycle;
structuredClone(withCycle); // works

Does not clone functions, DOM nodes, or symbols as keys the way you might hope — those throw or strip depending on type.

JSON round-trip (lossy)

const deep = JSON.parse(JSON.stringify(original));
Lost or changed Example
undefined, functions, symbols dropped
Date becomes string
NaN, Infinity null
Map / Set plain objects / empty
Cycles throw

Fine for simple JSON-shaped data. Wrong for real app state graphs.

Lodash cloneDeep / custom

Use when you need custom handling. Rolling your own recursive clone is a common interview task — remember cycles with a WeakMap.

function deepClone(value, seen = new WeakMap()) {
  if (value === null || typeof value !== 'object') return value;
  if (seen.has(value)) return seen.get(value);

  if (value instanceof Date) return new Date(value);
  if (value instanceof Map) {
    const m = new Map();
    seen.set(value, m);
    value.forEach((v, k) => m.set(deepClone(k, seen), deepClone(v, seen)));
    return m;
  }
  if (Array.isArray(value)) {
    const arr = [];
    seen.set(value, arr);
    value.forEach((v, i) => {
      arr[i] = deepClone(v, seen);
    });
    return arr;
  }

  const out = Object.create(Object.getPrototypeOf(value));
  seen.set(value, out);
  for (const key of Reflect.ownKeys(value)) {
    out[key] = deepClone(value[key], seen);
  }
  return out;
}

React / state angle

// wrong: mutate then setState same ref
state.items.push(item);
setItems(state.items); // may not re-render

// shallow copy top array + new item
setItems([...items, item]);

// nested update — copy each level you change
setUser({
  ...user,
  profile: { ...user.profile, bio: next },
});

You rarely need a full deep clone of the entire store — copy the path you write (immutability patterns).

Interview answer

“Assignment shares references. Shallow copies like spread clone one level; nested objects remain shared. structuredClone is the modern deep copy for many built-in types. JSON.parse/stringify is lossy. In UI state I copy only the update path, not the whole tree.”

Property descriptors and prototypes

const base = Object.create({ inherited: 1 });
base.own = 2;
const shallow = { ...base }; // only own enumerable: { own: 2 }

const full = structuredClone({ own: 2 }); // plain object, no prototype copy

Spread and Object.assign copy enumerable own properties only — getters are invoked and become data properties. structuredClone also does not clone prototype methods; you get data. If you need a clone that preserves class instances, write a type-aware clone or use a library designed for your domain objects — generic deep clone will surprise you.

Further reading

Related guides