Deep Copy vs Shallow Copy in JavaScript – What You Need to Know

Imagine you’re working on a complex JavaScript project, and you’ve got a nested object or array that’s crucial to your application’s functionality. You want to create a copy of it, modify the copy, and keep the original intact. Sounds simple, right? But here’s the catch: JavaScript’s default behavior can lead to unexpected results, and your modifications might affect the original data structure. This is where understanding shallow and deep copies becomes essential.

Shallow Copy: The Surface-Level Duplicate

A shallow copy creates a new object or array and populates it with references to the original elements. Think of it like creating a new folder with shortcuts to the original files. If you modify a primitive value (like a number or string) in the copied object, the original remains unaffected. However, if you modify a nested object or array, you’ll unintentionally change the original.

Example:

//Let's say you have an object with a name and an address:

const original = { name: 'Kalpesh', address: { street: '123 Main Street' } };

//You want to create a copy of this object, so you use a shallow copy method:

const shallowCopy = { ...original };

Now, shallowCopy is the new object that refrences the same element as original. If you will modify the name property in shallowCopy, it will won’t affect the original. But if you modify the address property, it will affect the original.

Methods for Shallow Copy:

Here are some of the common methods are as follows which helps for creating a shallow copy:

  1. Spread Operator( {. . .} ): const shallowCopy = { . . .original };
  2. Object.assign(): const shallowCopy = Object.assign({}, original);
  3. Array.prototype.slice(): const shallowCopy = original.slice(); (for arrays)
  4. Array.from(): const shallowCopy = Array.from(original); (for arrays)

Example with Spread Operator:

const original = { name: 'Kalpesh', address: { street: '123 Main Street' } };
const shallowCopy = { ...original };

shallowCopy.name = 'Kamlesh'; // won't affect original
console.log(original.name); // Output: "Kalpesh"

shallowCopy.address.street = '456 chouk Street'; // will affect original
console.log(original.address.street); // Output: "456 chouk Street"

in this example modifying the name property in shallowCopy doesn’t affect the original, but modifying the address.street property affects both shallowCopy and original.

When to use: The object contains only the primitive values or you don’t need full isolation of nested data

Deep Copying: A Solution to the Shallow Copy Problem

A deep copy is a way to create a completely independent copy of the object or array, recursively duplicating all nested elements. This means that if you modify a nested object or array in the copied object, it won’t affect the original object.

Example:

//Let's say you have an object with a name and an address:

const original = { name: 'Parth', address: { street: '123 Main Street' } };

//You want to create a deep copy of this object, so you use a deep copy method:

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

Now, deepCopy is a completely independent copy of original. If you will modify the name property or the address property in the deepCopy, it won’t affect the original.

Methods for Deep Copy:

Here are some of the common methods are as follows which helps for creating a deep copy:

  1. JSON.parse(JSON.stringify()): const deepCopy = JSON.parse(JSON.stringify(original));
  2. Lodash’s cloneDeep function: const deepCopy = _.cloneDeep(original);
  3. structuredClone() method: const deepCopy = structuredClone(original);

Example with JSON.parse(JSON.stringify()):

const original = { name: 'Parth', address: { street: '123 Main Street' } };
const deepCopy = JSON.parse(JSON.stringify(original));

deepCopy.name = 'Varun'; // won't affect original
console.log(original.name); // Output: "Parth"

deepCopy.address.street = '456 Chouk Street'; // won't affect original
console.log(original.address.street); // Output: "123 Main Street"

In this above example, modifying the name property or the address.street property in the deepCopy doesn’t affect the original. Both the objects are completely independent.

When to use: whenever you needed a fully independent copy, especially for nested or complex structures.

Comparison between Shallow Copy and Deep Copy :

Feature Shallow Copy Deep Copy
Top-level copy  Yes Yes
Nested copy  No (references shared)  Yes (full duplication)
Performance  Fast Slower (more memory/processing)
Methods Spread, Object.assign JSON, structuredClone, Lodash
Use Case Simple, flat objects Complex, deeply nested objects
Memory Allocation Shares references for nested objects (low memory usage) Allocates new memory for all nested data (high memory usage)
Mutation Safety Risk of accidental mutation due to shared references Safe from accidental mutation; full isolation
Support for Circular References Fails or loops if manually implemented Can be supported with libraries like Lodash or structuredClone
Function Copying Copies function references as-is Usually skipped unless using advanced libraries
Serialization No serialization step involved Often uses serialization (e.g., JSON) which omits special data types
Debugging Ease Harder to debug shared state issues Easier to debug due to full isolation
Conclusion:

Understanding the differences between the shallow and deep copies in javascript is very crucial for writing the predictable and maintainable code. By using modern best practices and libraries, you can ensure that your code behaves as the expected, even when working with complex data structures.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top