Understanding Object Copying in JavaScript: Shallow Copy vs. Deep Copy

Table of contents

No heading

No headings in the article.

In JavaScript, copying objects is a common operation when working with data. However, it's essential to understand the differences between shallow copy and deep copy to avoid unexpected side effects and maintain data integrity. In this blog post, we'll explore the concepts of shallow copy and deep copy, discuss their implications, and provide examples of different ways to perform object copying.

1. What is Shallow Copy?

Shallow copy refers to creating a new object that references the original object's properties. In other words, the copied object shares the same references to nested objects or arrays present in the original object. Any modifications made to these shared references will be reflected in both the original and copied objects.

2. Implications of Shallow Copy

When working with complex data structures, shallow copying can lead to unintended consequences. Modifying a shared reference can affect multiple objects, potentially causing data inconsistencies. It's crucial to be aware of this behavior to ensure data integrity.

3. Ways to Perform Shallow Copy

a. Assignment Operator

The assignment operator (=) performs a shallow copy by creating a new reference to the original object. However, it fails to create an independent copy when dealing with nested objects or arrays, including its top-level properties. Instead, it copies the reference to the nested object, which means that modifications to the nested object will affect both the original and copied objects.

Consider the following example:

const originalObject = {
  name: 'John',
  age: 25,
  address: {
    city: 'New York',
    country: 'USA',
  },
};

const copiedObject = originalObject;

copiedObject.address.city = 'San Francisco';
copiedObject.name = 'Sam';

console.log(originalObject.address.city); // Output: San Francisco
console.log(originalObject.name); // Sam

In this case, modifying the address.city property in the copied object affects the original object as well because both objects share the same reference to the nested address object.

b. Object.assign()

The Object.assign() method is commonly used to perform shallow copies. While it allows you to create a new object with properties from the original object, it also falls short when dealing with nested objects or arrays. Similar to the assignment operator, it copies the references to nested objects instead of creating independent copies.

Consider the following example:

const originalObject = {
  name: 'John',
  age: 25,
  address: {
    city: 'New York',
    country: 'USA',
  },
};

const copiedObject = Object.assign({}, originalObject);

copiedObject.address.city = 'San Francisco';
copiedObject.name = 'Sam';

console.log(originalObject.address.city); // Output: San Francisco
console.log(originalObject.name); // John

As in the previous example, modifying the address.city property in the copied object affects the original object due to the shared reference to the nested address object.

In scenarios where you require a complete copy, including nested objects, a deep copy method such as JSON.parse() and JSON.stringify() or Lodash's cloneDeep() is recommended. These methods ensure that nested objects are also copied, creating independent copies that won't be affected by modifications to the original object.

c. Spread Syntax

The spread operator (...) can be considered an advanced version of Object.assign() when it comes to object copying. While both approaches perform shallow copies of objects, the spread operator provides some additional benefits and a more concise syntax.

const originalObject = { name: 'John', age: 25 };
const copiedObject = { ...originalObject };

4. What is Deep Copy?

Deep copy involves creating an entirely new object with its own set of properties and values. Nested objects or arrays within the original object are also recursively copied, resulting in independent copies that are not affected by modifications made to the original or other copies.

5. Implications of Deep Copy

Deep copying ensures data isolation and prevents unintended side effects. Each copy maintains its own set of values, allowing for independent modifications without affecting other objects.

6. Ways to Perform Deep Copy

a. JSON.parse() and JSON.stringify()

const originalObject = { name: 'John', age: 25 };
const copiedObject = JSON.parse(JSON.stringify(originalObject));

b. Lodash's cloneDeep()

const originalObject = { name: 'John', age: 25 };
const copiedObject = _.cloneDeep(originalObject);

7. Conclusion

Understanding the concepts of shallow copy and deep copy is essential for proper object copying in JavaScript. Shallow copy creates new objects that reference the original, while deep copy ensures complete data isolation. Depending on your requirements, choose the appropriate method to perform object copying.

To perform shallow copy, you can use the assignment operator, Object.assign(), or the spread syntax. If you need a deep copy, options include JSON.parse() and JSON.stringify(), as well as libraries like Lodash's cloneDeep().

By selecting the right copying method, you can maintain data integrity, prevent unexpected mutations, and ensure reliable code execution in your JavaScript projects.

Hopefully, this blog post has provided a comprehensive understanding of shallow copy and deep copy, as well as the various methods

Did you find this article valuable?

Support Insightful Bytes by becoming a sponsor. Any amount is appreciated!