Deep Copy vs Shallow Copy: Get It Right and Never Run Into Data Bugs Again

Have you ever changed a 'new' object only to see the original object change with it? This common JavaScript bug comes from confusing shallow vs deep copy. Learn how memory works and pick the right method, especially for complex state in React or Redux.

deep copyshallow copyJavaScript
Cover image: Deep Copy vs Shallow Copy: Get It Right and Never Run Into Data Bugs Again
Avatar of Trung Vũ Hoàng

Trung Vũ Hoàng

Author

30/3/20264 min read

1. Value vs Reference — The Root of the Problem

JavaScript treats two groups of data types very differently:

  • Primitive types: string, number, boolean... — when you assign a = b, an independent copy of the value is created. Changing a does not affect b.

  • Reference types: Object, Array — when you assign obj2 = obj1, JavaScript does not create a new object. It only creates another "path" (reference) pointing to a single memory location on the Heap. This is the root of the confusion.

2. Shallow Copy — Surface-Level Copy, Danger Beneath

A shallow copy creates a new object, but only copies the top-level properties:

  • Primitive-typed properties → copied by value, safe.

  • Nested Object/Array properties → only the reference is copied, still sharing memory with the original.

Common syntax for shallow copy: { ...obj } (Spread), Object.assign({}, obj).

const original = { name: "JS", meta: { version: 1 } };
const copy = { ...original };

copy.name = "Python";       // OK — original.name remains unchanged
copy.meta.version = 99;     // DANGEROUS — original.meta.version also becomes 99!

Shallow copy is very useful when the object is "flat" (no nesting). But with multi-level JSON returned from an API, it’s a ticking time bomb.

3. Deep Copy — Fully Independent, No Shared Links

A deep copy walks through every level of the object and creates a brand-new clone at every level — leaving no memory links to the original. Changing the copy will never affect the original, no matter how deep the nesting.

Deep copy is commonly used for: state snapshots, Undo/Redo features, and data processing that requires strong immutability.

4. Methods to Perform a Deep Copy

JSON.parse(JSON.stringify(obj))

const deepCopy = JSON.parse(JSON.stringify(original));

Fast and simple — but loses data with special types: Date, undefined, Function, RegExp. Use only when the object is guaranteed to be plain JSON.

structuredClone() — Modern API, No Library Needed

const deepCopy = structuredClone(original);

Available on modern browsers and Node.js 17+. Faster than JSON and handles more types (Date, Map, Set...). This is the best choice for most cases.

Lodash _.cloneDeep()

import cloneDeep from 'lodash/cloneDeep';
const deepCopy = cloneDeep(original);

The "gold standard" in large projects — handles circular references and complex data types. Suitable when your project already includes Lodash.

5. When to Use Shallow vs Deep?

  • Use a shallow copy when: The object is "flat" (no nesting), or you intentionally want child objects to be shared to save memory.

  • Use a deep copy when: You handle multi-level data, need strict immutability, or implement Undo/Redo.

6. Performance Considerations

Deep-copying a large object with thousands of elements can make the app stutter — because the engine must traverse the entire data tree.

Optimization tip: When you only need to change a small part of a nested object, use the Immutable Update Pattern (common in Redux Toolkit) — create new objects only for the levels you change, keep the old references for the rest:

const newState = {
  ...state,
  user: {
    ...state.user,
    name: "Updated"  // Only the user level is recreated
  }
};

7. Summary

Distinguishing deep copy vs shallow copy is not just about syntax — it’s a mindset about memory architecture. A good developer knows exactly which memory their code touches:

  • Flat object + performance first → Spread / Object.assign (shallow).

  • Nested object + needs independence → structuredClone (deep, no library).

  • Large projects, complex data → Lodash _.cloneDeep (deep, most comprehensive).

Frequently Asked Questions

Share this article
Zalo

Found this article helpful?

Contact us for a free consultation about our services

Contact us

Bài viết liên quan