πŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
πŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
JS MASTER CLASS /// MASTER THE ENGINE /// BUILD LOGIC /// ASYNC PATTERNS /// JS MASTER CLASS /// MASTER THE ENGINE ///

Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide

Understand the precise difference between shallow and deep copies, why most native copy methods are shallow, and the trade-offs of different deep-copy strategies.

⚑ Total XP: 0|πŸ’» javascript XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

Does spreading an object (`{ ...obj }`) create independent copies of its nested objects?


πŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
πŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Every copying technique in JavaScript β€” spread, Object.assign, Array.slice β€” is shallow by default. Knowing exactly when a shallow copy is enough, and when you truly need a deep copy, prevents an entire category of "mystery mutation" bugs.

1Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide Part 1

A shallow copy duplicates an object's top-level properties, but any property holding a reference type still points at the exact same nested object.

βœ•
β€”
+
const original = { user: { name: 'Al' } };
const shallow = { ...original };
shallow.user.name = 'Bo';
original.user.name; // 'Bo' β€” shared reference!
localhost:3000
πŸͺž

Shallow Copy Recap

2Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide Part 2

A deep copy recursively duplicates every nested level, guaranteeing the copy and original share absolutely no references.

βœ•
β€”
+
const deep = JSON.parse(JSON.stringify(original));
deep.user.name = 'Carla';
original.user.name; // still 'Bo', unaffected
localhost:3000

True Deep Copy

3Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide Part 3

The JSON.parse(JSON.stringify(x)) trick is a common but flawed deep-copy technique β€” it silently drops functions, undefined, Dates become strings, and it throws on circular references.

βœ•
β€”
+
JSON.parse(JSON.stringify({ fn() {}, d: new Date(), u: undefined }));
// { d: '2024-01-01T00:00:00.000Z' } β€” fn and u are gone!
localhost:3000

The JSON Trick's Flaws

4Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide Part 4

A hand-written recursive deep-clone function correctly handles nested objects and arrays, but must be written carefully to avoid infinite loops on circular references.

βœ•
β€”
+
function deepClone(value, seen = new WeakMap()) {
  if (typeof value !== 'object' || value === null) return value;
  if (seen.has(value)) return seen.get(value);
  const clone = Array.isArray(value) ? [] : {};
  seen.set(value, clone);
  for (const key in value) clone[key] = deepClone(value[key], seen);
  return clone;
}
localhost:3000

Hand-Written Deep Clone

5Deep Copy vs Shallow Copy | JavaScript Tutorial - In-Depth Guide Part 5

Most of the time, a shallow copy is exactly what you want and is far cheaper β€” reach for deep copying only when you know nested data must be fully independent.

βœ•
β€”
+
// Shallow is enough here β€” you control every level explicitly:
const next = { ...state, user: { ...state.user, name } };
localhost:3000

Choosing the Right Depth

6Step-by-Step Breakdown

A shallow copy duplicates an object's top-level properties, but any property holding a reference type still points at the exact same nested object.

Checkpoint: Does spreading an object ({ ...obj }) create independent copies of its nested objects?

  • β†’Yes, spread is a full deep copy
  • β†’No, nested objects remain shared references

A deep copy recursively duplicates every nested level, guaranteeing the copy and original share absolutely no references.

The JSON.parse(JSON.stringify(x)) trick is a common but flawed deep-copy technique β€” it silently drops functions, undefined, Dates become strings, and it throws on circular references.

Checkpoint: Does JSON.parse(JSON.stringify(obj)) correctly preserve a function property on the object?

  • β†’Yes, functions survive the round-trip
  • β†’No, functions are silently dropped

A hand-written recursive deep-clone function correctly handles nested objects and arrays, but must be written carefully to avoid infinite loops on circular references.

Most of the time, a shallow copy is exactly what you want and is far cheaper β€” reach for deep copying only when you know nested data must be fully independent.

Next, we'll explore 'structuredClone()'.

Level Up πŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Deep-Copy Editor State Before Presenting an Undo Preview

An accessible undo/redo feature that announces 'previous version restored' via a live region needs a genuinely independent deep-copied snapshot, so the preview shown to assistive technology cannot be silently altered by ongoing edits to the live document.

SEO Implications

  • 1

    No Direct SEO Effect

    Copy semantics are a data-integrity concern; their SEO relevance is limited to preventing state-corruption bugs that could produce inconsistent rendered content.

Best Practices

Default to Shallow Copies, and Update Each Nested Level Explicitly

Explicitly spreading each level you intend to change (`{ ...state, user: { ...state.user, name } }`) is usually clearer and cheaper than reaching for a full deep copy of the entire state tree.

Avoid the JSON.stringify/parse Trick for Anything But Simple, Serializable Data

It silently corrupts functions, undefined, Dates, Maps, Sets, and throws on circular references β€” use structuredClone() or a proper library for anything beyond plain JSON-safe data.

Frequent Bugs

THE BUG

Believing `{ ...state }` fully isolates a copy of application state, then discovering a deeply nested mutation in one part of the app silently affected another part relying on the 'original' state.

THE FIX

Identify exactly which levels of the structure are mutated and copy each of those levels explicitly, or use a proper deep-copy utility if the whole tree must be independent.

THE BUG

Using JSON.parse(JSON.stringify(data)) to clone data containing a Date, and later code breaking because it expected a Date instance but received a string.

THE FIX

Use structuredClone() instead, which correctly preserves Date, Map, Set, and other structured-clonable types, or manually re-hydrate Dates after a JSON round-trip.

Real-World Examples

Cloning a Document Before an Undoable Edit

A rich-text or diagram editor needed to snapshot the entire document state before an edit so the user could undo back to it, requiring full independence between the snapshot and the live document.

function snapshotForUndo(document) {
  return structuredClone(document); // full deep copy, safe for later mutation
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Assuming any spread-based copy is deep

const trueCopy = structuredClone(nestedData);

The Solution //

Remember spread, Object.assign, and slice are all shallow; use structuredClone() or a recursive utility when true independence is required at every level.

Lesson Glossary

[01]Shallow Copy

A copy that duplicates only the top level of an object or array.

Code Preview
{ ...obj }

[02]Deep Copy

A copy where every nested level is independently duplicated, sharing no references with the original.

Code Preview
deepClone(obj)

[03]Circular Reference

An object that references itself, directly or indirectly, causing naive recursive algorithms to loop forever.

Code Preview
a.self = a

[04]JSON Round-Trip Clone

A flawed deep-copy technique using JSON.parse(JSON.stringify(x)) that drops functions/undefined and mishandles Dates.

Code Preview
JSON.parse(JSON.stringify(x))

[05]WeakMap Tracking

Using a WeakMap to track already-cloned objects, preventing infinite loops on circular structures.

Code Preview
new WeakMap()

Continue Learning