advanced

Deep Clone Object

Create a deep copy of a nested object.

Object cloning is essential for working with immutable data and avoiding unintended mutations. This exercise teaches you the difference between shallow and deep cloning and when to use each approach.

📚 Concepts & Theory

Cloning objects in JavaScript is tricky because objects are reference types. Understanding shallow vs deep cloning is crucial for avoiding bugs with nested data structures.

Understanding Object Cloning:

Shallow Clone Methods:

1. Spread Operator (ES6+) - Shallow Only

const original = { a: 1, b: { c: 2 } };
const clone = { ...original };
// clone.b === original.b (same reference!)

2. Object.assign() - Shallow Only

const clone = Object.assign({}, original);

Deep Clone Methods:

1. JSON Methods (Most Common, Has Limitations)

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

Limitations of JSON Method:

  • ❌ Loses functions

  • ❌ Loses undefined values

  • ❌ Loses Dates (becomes string)

  • ❌ Loses RegExp, Map, Set

  • ❌ Circular references cause errors
2. structuredClone() (Modern, Recommended)
const deepClone = structuredClone(original);  // Available in Node 17+, modern browsers

3. Recursive Deep Clone:

function deepClone(obj) {
if (obj === null || typeof obj !== "object") return obj;

const clone = Array.isArray(obj) ? [] : {};

for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}

4. Libraries:

// Lodash
const clone = _.cloneDeep(original);

Understanding the Difference:

const original = { 
    level1: { 
        level2: { value: 42 } 
    } 
};

// Shallow clone
const shallow = { ...original };
shallow.level1.level2.value = 999;
console.log(original.level1.level2.value); // 999 - mutated original!

// Deep clone
const deep = JSON.parse(JSON.stringify(original));
deep.level1.level2.value = 999;
console.log(original.level1.level2.value); // 42 - original unchanged

🎯 Your Challenge

Write deepClone that creates a deep copy.

📝 Starter Code

JavaScript
function deepClone(obj) {
  // Your code here
}

const original = {a: 1, b: {c: 2}};
const copy = deepClone(original);
  • You need to clone nested objects, not just the top level
  • Spread operator {...obj} only does shallow clone
  • JSON.stringify() converts object to string
  • JSON.parse() converts string back to object
  • Combining both JSON methods creates a deep clone

Solution

JavaScript
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

const original = {a: 1, b: {c: 2}};
const copy = deepClone(original);
copy.b.c = 999;
console.log(original.b.c); // Still 2

Explanation

This solution uses JSON.parse(JSON.stringify(obj)) to create a deep clone. The process works by: 1) JSON.stringify() converts the object to a JSON string representation, 2) JSON.parse() parses that string back into a new object. This creates completely new objects at all nesting levels, breaking all references to the original. While this method has limitations (loses functions, undefined, Dates), it's the simplest approach for plain data objects. Time complexity: O(n) where n is total number of properties. Space complexity: O(n) for the clone plus O(n) temporary string.

⚠️ Common Mistakes to Avoid

  • Using spread operator for nested objects (only shallow clones)
  • Thinking Object.assign() creates deep clone
  • Not handling circular references
  • Forgetting that JSON method loses functions and undefined
  • Modifying what you think is a clone but is actually a reference

❓ Frequently Asked Questions

Shallow clone copies top-level properties, keeping references to nested objects. Deep clone recursively copies all levels, creating entirely new objects.
Spread operator only copies one level. Nested objects are still referenced, not cloned.
It loses functions, undefined values, Dates, and can't handle circular references.
Use structuredClone() in modern environments, or libraries like Lodash for complex cases.

🔗 Related Exercises