DEV Community

Cover image for JavaScript Shallow Copy vs Deep Copy: Examples and Best Practices
Harish Kumar
Harish Kumar

Posted on • Edited on

JavaScript Shallow Copy vs Deep Copy: Examples and Best Practices

When working with objects and arrays in JavaScript, creating copies of data structures is a common task. However, developers often face challenges when deciding between a shallow copy and a deep copy. Misunderstanding the differences can lead to unintended side effects in your code. Let’s dive into these concepts, their differences, and when to use each.


👉 Download eBook - JavaScript: from ES2015 to ES2023

javascript-from-es2015-to-es2023


What Is a Shallow Copy?

A shallow copy creates a new object with copies of the top-level properties of the original object. For properties that are primitives (e.g., numbers, strings, booleans), the value itself is copied. However, for properties that are objects (like arrays or nested objects), only the reference is copied—not the actual data.

This means that while the new object has its own copy of top-level properties, the nested objects or arrays remain shared between the original and the copy.

Example of a Shallow Copy

const original = {
  name: "Alice",
  details: {
    age: 25,
    city: "Wonderland"
  }
};

// Shallow copy
const shallowCopy = { ...original };

// Modify the nested object in the shallow copy
shallowCopy.details.city = "Looking Glass";

// Original object is also affected
console.log(original.details.city); // Output: "Looking Glass"
Enter fullscreen mode Exit fullscreen mode

How to Create a Shallow Copy

  1. Using the Spread Operator (...):
   const shallowCopy = { ...originalObject };
Enter fullscreen mode Exit fullscreen mode
  1. Using Object.assign():
   const shallowCopy = Object.assign({}, originalObject);
Enter fullscreen mode Exit fullscreen mode

While these methods are fast and easy, they are not suitable for deeply nested objects.


What Is a Deep Copy?

A deep copy duplicates every property and sub-property of the original object. This ensures that the copy is completely independent of the original, and changes to the copy do not affect the original object.

Deep copying is essential when dealing with complex data structures like nested objects or arrays, particularly in scenarios where data integrity is critical.

Example of a Deep Copy

const original = {
  name: "Alice",
  details: {
    age: 25,
    city: "Wonderland"
  }
};

// Deep copy using JSON methods
const deepCopy = JSON.parse(JSON.stringify(original));

// Modify the nested object in the deep copy
deepCopy.details.city = "Looking Glass";

// Original object remains unchanged
console.log(original.details.city); // Output: "Wonderland"
Enter fullscreen mode Exit fullscreen mode

How to Create a Deep Copy

  1. Using JSON.stringify() and JSON.parse():
    • Converts the object into a JSON string and then parses it back into a new object.
    • Limitations:
      • Cannot handle circular references.
      • Ignores properties like functions, undefined, or Symbol.
   const deepCopy = JSON.parse(JSON.stringify(originalObject));
Enter fullscreen mode Exit fullscreen mode
  1. Using Libraries:
    • Libraries like Lodash provide robust deep cloning methods.
   const _ = require('lodash');
   const deepCopy = _.cloneDeep(originalObject);
Enter fullscreen mode Exit fullscreen mode
  1. Custom Recursive Function:
    • For full control, you can write a recursive function to clone nested objects.

Comparing Shallow Copy and Deep Copy

Feature Shallow Copy Deep Copy
Scope Copies only top-level properties. Copies all levels, including nested data.
References Nested references are shared. Nested references are independent.
Performance Faster and lightweight. Slower due to recursive operations.
Use Cases Flat or minimally nested objects. Deeply nested objects or immutable structures.

When to Use Shallow Copy

  • Flat Objects: When dealing with simple objects without nested properties.
  • Performance: When speed is crucial, and you don’t need to handle deeply nested data.
  • Temporary Changes: When you intend to modify top-level properties but share nested data.

Example Use Case

Copying a user’s settings object to make quick adjustments:

const userSettings = { theme: "dark", layout: "grid" };
const updatedSettings = { ...userSettings, layout: "list" };
Enter fullscreen mode Exit fullscreen mode

When to Use Deep Copy

  • Complex Structures: For objects with multiple levels of nesting.
  • Avoiding Side Effects: When you need to ensure that changes in the copy don’t affect the original.
  • State Management: In frameworks like React or Redux, where immutability is critical.

Example Use Case

Duplicating the state of a game or application:

const gameState = {
  level: 5,
  inventory: {
    weapons: ["sword", "shield"],
    potions: 3
  }
};

// Deep copy ensures no side effects
const savedState = JSON.parse(JSON.stringify(gameState));
Enter fullscreen mode Exit fullscreen mode

Common Mistakes and Pitfalls

  1. Assuming Shallow Copy Is Always Sufficient:

    • Developers often mistakenly use shallow copy methods for nested objects, leading to unintended changes in the original data.
  2. Overusing JSON Methods:

    • While JSON.stringify/JSON.parse is simple, it doesn’t work for all objects (e.g., those containing methods or circular references).
  3. Neglecting Performance:

    • Deep copy methods can be slower, especially for large objects, so use them judiciously.

Conclusion

Understanding the difference between shallow copy and deep copy is essential for writing bug-free JavaScript code. Shallow copies are efficient for flat structures, while deep copies are indispensable for complex, nested objects. Choose the appropriate method based on your data structure and application needs, and avoid potential pitfalls by knowing the limitations of each approach.


👉 Download eBook - JavaScript: from ES2015 to ES2023

javascript-from-es2015-to-es2023

Top comments (6)

Collapse
 
miketalbot profile image
Mike Talbot ⭐

You've completely missed structuredClone() as a way of deep copying - the built in function for it should be here! structuredClone

Collapse
 
jankapunkt profile image
Jan Küster

Should be the preferred method, if supported by the browser/runtime

Collapse
 
seasle profile image
Alexander Munko

I would like to see a native way of deep cloning - structuredClone, and more correct limitations for JSON.parse together with JSON.stringify in the article.

Collapse
 
smpnjn profile image
Johnny Simpson • Edited

structuredClone() is the best way to make a deep copy. JSON.parse and JSON.stringify does not work with all data types. undefined, function and Symbol objects will disappear from your object if you try to make a deep copy with that functionality. Should be avoided unless absolutely necessary.

Collapse
 
avidys profile image
Jean M

Freebies (mozilla.org should be the first step): Shallow copy, Deep copy

Note that structuredClone is not part of JavaScript per se but is widely available

Better discussion on deep-cloning algorithms at Structured_clone_algorithm

Some comments may only be visible to logged-in visitors. Sign in to view all comments.