Mastering Shallow Copy and Deep Copy in JavaScript

Page 1

Shallow Copy vs Deep Copy in JavaScript: Which One Should You Use?

AUTHOR

Tien Nguyen

Home  Tutorials  Shallow Copy vs Deep Copy in JavaScript: Which One Should You Use?
DATE May 3, 2023
a JavaScript developer, you must be familiar with the concept of copying, which is        
website uses cookies to ensure you get the best experience on our website. Learn more x
CATEGORY Tutorials As
This

the process of creating a new object or array with the same values as an existing one.

Copying is an essential technique in programming that helps you to avoid unexpected mutations to objects and arrays There are two main techniques for copying in JavaScript: shallow copy and deep copy.

In this article, we’ll explore the di몭erences between shallow copy vs deep copy in JavaScript and when to use each technique We’ll also discuss the bene몭ts and limitations of each approach and provide you with best practices to help you avoid common pitfalls.

By the end of this post, you’ll have a better understanding of how to use shallow copy and deep copy in your code e몭ectively. So, let’s dive in!

Table of Contents

1 Shallow Copy in JavaScript

1.1. Spread Operator

1 2 Object assign()

1.3. Array.slice()

2 Deep Copy in JavaScript

2.1. JSON.parse(JSON.stringify())

2 2 lodash cloneDeep()

2.3. Recursive Function

3 Comparing Shallow Copy vs Deep Copy in JavaScript

3.1. Level of Copying

3 2 Reference Handling

3.3. Performance

3 4 Circular References

4 Pros and Cons of Shallow Copy

4.1. Pros

4 2 Cons

5. Pros and Cons of Deep Copy

Got it

5 1 Pros

5.2. Cons

6 Use Cases for Shallow Copy and Deep Copy

6.1. When to Use Shallow Copy

6 2 When to Use Deep Copy

7. Common Pitfalls and Best Practices

71 Modifying Original Objects or Arrays

7.2. Performance Considerations

7 3 Choosing the Right Copying Method

7.4. Using Libraries and Frameworks

8. Conclusion

Shallow Copy in JavaScript

JavaScript provides multiple ways to create shallow copies of objects and arrays.

When you make a shallow copy of an object or array, you create a new one that points to the same values as the original If you change the original object or array, the shallow copy will also change. Reversely, if you change the shallow copy, the original object or array will also be a몭ected.

A shallow copy does not clone nested objects, meaning that if the original object contains other objects or arrays as properties, the shallow copy will point to the same references as the original.

Spread Operator

9 FAQs …

One common way to create a shallow copy of an object or an array in JavaScript is to use the spread operator ( ) The spread operator copies all enumerable properties of an object or an array into a new one. For example:

1. // Create an original object

2. let person = {

3 name: 'Alice',

4 age: 25,

5 hobbies: ['reading', 'writing', 'coding'], 6 }

7.

//

9. let personCopy = { ...person }

8. Create a shallow copy using the spread operator
10.

11 // Modify the original object

12. person.name = 'Bob'

13.

14. // Check the shallow copy

15. console.log(personCopy.name) // Alice

16 console.log(personCopy.hobbies) // ["reading", "writing", "coding"]

17

18 // Modify the shallow copy

19 personCopy.hobbies.push('gaming')

20.

21. // Check the original object

22. console.log(person.hobbies) // ["reading", "writing", "coding", "gaming"]

As you can see, the spread operator makes a copy of an object and its properties; however, it doesn’t create a copy of nested arrays within the object. Therefore, when we modify the property of either object, the change a몭ects both objects

hobbies

Object.assign()

Another way to create a shallow copy of an object is to use the method. It copies all the enumerable and own properties of one or more source objects into a target object. For instance:

1 // Create an original object

2. let person = {

3. name: 'Alice',

4. age: 25,

5. hobbies: ['reading', 'writing', 'coding'], 6 } 7

8 // Create a shallow copy using Object.assign()

9 let personCopy = Object.assign({}, person)

10.

11. // Modify the original object

12. person.name = 'Bob'

13.

14. // Check the shallow copy

15 console.log(personCopy.name) // Alice

Object.assign()

16 console log(personCopy hobbies) // ["reading", "writing", "coding"]

17

18 // Modify the shallow copy 19. personCopy.hobbies.push('gaming')

20.

21. // Check the original object 22. console.log(person.hobbies) // ["reading", "writing", "coding", "gaming"]

Object.assign()

The method works similarly to the spread operator, except that it can take multiple source objects as arguments and merge them into the target object. However, it also does not clone nested objects, so modifying them will a몭ect both objects

Array.slice()

To create a shallow copy of an array, you can use the method. This method returns a new array with a portion of the original array. If no arguments are provided, it returns a copy of the whole array.

Array.slice()

The method creates a new array with the same elements as the original array, but it does not clone nested arrays or objects. Therefore, modifying them will a몭ect both arrays. Here’s an example:

Array.slice()

1 // Create an original array with a nested array and an object as elements

=

Create a new array using Array.slice()

Check the values and references of the original array and the

{name: "Alice", age:

{name: "Alice", age: 25}]

(originalArray[0] === newArray[0]); // true

// Modify the nested array and the object in the original array

originalArray[0] push(4);

originalArray[1].name = "Bob";

// Check the values and references of the original array and the new array

console.log(originalArray); // [[1, 2, 3, 4], {name: "Bob", age: 25}]

console log(newArray); // [[1, 2, 3, 4], {name: "Bob", age: 25}]

Deep Copy in JavaScript

Creating a deep copy of an object or an array in JavaScript involves duplicating the

2
; 3. 4.
5. let newArray
; 6 7
8 console.log(originalArray); // [[1, 2, 3],
25}] 9 console.log(newArray); // [[1, 2, 3],
10.
11.
12 13
14
15
16. 17.
18.
20
21
let originalArray
[[1, 2, 3], {name: "Alice", age: 25}]
//
= originalArray.slice()
//
new array
console.log
console.log(originalArray[1] === newArray[1]); // true
19
console.log(originalArray[0] === newArray[0]); // true
console.log(originalArray[1] === newArray[1]); // true

original object’s properties and values, including any nested objects or arrays, into a new object or array without any shared references. This means that changes made to one object or array will not a몭ect the other.

There are various ways to create a deep copy:

JSON.parse(JSON.stringify())

JSON.parse(JSON.stringify())

One simple method is using the method, which converts an object or array into a JSON string and then parses it back into a new object or array For instance:

1 // Create an original object

2 let person = {

3 name: 'Alice',

4 age: 25,

5. hobbies: ['reading', 'writing', 'coding'],

6. }

7.

8 // Create a deep copy using JSON parse(JSON stringify())

9 let personCopy = JSON parse(JSON stringify(person)) 10

11 // Modify the original object 12 person.name = 'Bob' 13

14. // Check the deep copy

15. console.log(personCopy.name) // Alice

16. console.log(personCopy.hobbies) // ["reading", "writing", "coding"] 17 18 // Modify the deep copy

personCopy.hobbies.push('gaming')

21 // Check the original object

22. console.log(person.hobbies) // ["reading", "writing", "coding"]

As you can see, the method creates a new object with the same values and properties as the original object, but it also clones the nested array Therefore, when we modify the hobbies property of either object, the change does not a몭ect the other object.

lodash.cloneDeep()

JSON.parse(JSON.stringify()) lodash

Another way is to use a third-party library such as , which provides the method that recursively clones an object or an array and any nested objects or arrays For example:

cloneDeep()

19
20

1. // Import lodash.cloneDeep

2. import cloneDeep from 'lodash/cloneDeep'

3

4 // Create an original object

5 let person = {

6 name: 'Alice',

7. age: 25,

8. hobbies: ['reading', 'writing', 'coding'],

}

11 // Create a deep copy using lodash cloneDeep() 12 let personCopy = cloneDeep(person)

14 // Modify the original object

15 person.name = 'Bob'

16.

17. // Check the deep copy

18. console.log(personCopy.name) // Alice

19. console.log(personCopy.hobbies) // ["reading", "writing", "coding"]

20

21 // Modify the deep copy

22 personCopy.hobbies.push('gaming')

23

24. // Check the original object

25. console.log(person.hobbies) // ["reading", "writing", "coding"]

lodash.cloneDeep()

JSON.parse(JSON.stringify())

The function works similarly to the method, except that it does not rely on JSON serialization and deserialization It also does not clone functions or symbols, so it may not work for some complex objects.

JSON.parse(JSON.stringify())

lodash.cloneDeep()

However, unlike , can handle circular references and unde몭ned values, and it can clone other data types or methods that JSON cannot serialize, such as dates, regexes, maps, sets, etc., by using customizer functions or plugins.

Recursive Function

Alternatively, you can write a custom recursive function that iterates over the properties of an object or an array and creates new copies of them For instance:

1 // Create a custom function for deep copying

2 function deepCopy(obj) {

3 // Check if obj is an array or an object

4 if (Array.isArray(obj)) {

5. // Create a new array and loop over its elements

10
9.
13

6. let newArr = []

7. for (let i = 0; i < obj.length; i++) {

8. // Recursively call deepCopy on each element and push it to newArr 9 newArr push(deepCopy(obj[i]))

} 11 // Return newArr

12. return newArr

13. } else if (typeof obj === 'object' && obj !== null) {

14. // Create a new object and loop over its keys 15 let newObj = {}

16 for (let key in obj) { 17 // Recursively call deepCopy on each value and assign it to newObj[key]

}

newObj[key] = deepCopy(obj[key])

// Return newObj

return newObj

} else {

// Return obj as it is (primitive value)

return obj

}

}

// Create an original object

let person = {

name: 'Alice',

age: 25,

hobbies: ['reading', 'writing', 'coding'],

}

// Create a deep copy using deepCopy()

let personCopy = deepCopy(person)

// Modify the original object

person.name = 'Bob'

// Check the deep copy

console.log(personCopy.name) // Alice

console.log(personCopy.hobbies) // ["reading", "writing", "coding"]

// Modify the deep copy

personCopy hobbies push('gaming')

// Check the original object

console.log(person.hobbies) // ["reading", "writing", "coding"] deepCopy() hobbies

You can see that the function returns a new object with the same values and properties as the original object, but it also clones the nested array Therefore, when we modify the property of either object, the change does not a몭ect

10
19.
20.
21
22
23
24
25.
26.
27 28
29
30
31
32
33.
34. 35.
36
37 38
39
40 41
42.
43.
44 45
46
47 48
49
18

the other object.

Comparing Shallow Copy vs Deep Copy in JavaScript

Now that we have a good understanding of what shallow copy and deep copy are, let’s take a closer look at the di몭erences between them.

Key

Di몭erenc e Shallow Copy Deep Copy

Level of Copying

Reference Handling

Performan ce

Copies only top-level properties or elements

Copies references to nested objects or arrays

Less expensive in terms of performance and memory usage

Creates a complete and independent copy of the entire object or array, including all nested objects or arrays

Creates new instances of all nested objects or arrays

More expensive in terms of performance and memory usage

Key

Di몭erenc e Shallow Copy

Circular Reference s

Handles circular references better

Level of Copying

Deep Copy

Creates circular references in the copy

The primary di몭erence between shallow copy and deep copy is the level of copying they perform. Shallow copy only copies the top-level properties or elements of an object or array, while deep copy creates a complete and independent copy of the entire object or array, including all nested objects or arrays.

Reference Handling

Another signi몭cant di몭erence between shallow copy and deep copy is how they handle references. Shallow copy only copies references to nested objects or arrays, while deep copy creates new instances of all nested objects or arrays.

Performance

Deep copy can be more expensive in terms of performance and memory usage than shallow copy This is because deep copy requires more processing power and memory to create and store a complete copy of the original object or array.

Circular References

Shallow copy can handle circular references better than deep copy. When copying an object or array with a circular reference, shallow copy will copy the reference to the original object or array, while deep copy will also create a circular reference in the copy

Pros and Cons of Shallow Copy

Here are some of the pros and cons of using shallow copy in JavaScript:

Pros

Saves Memory: Shallow copy can be useful in cases where you want to save memory by avoiding the creation of a completely new object or array By copying

only the top-level properties or elements of the original object or array, you can save memory without a몭ecting the original object or array.

Quick and Simple: Shallow copy is generally faster and simpler than deep copy, since it only copies the top-level properties or elements of an object or array This can be useful in cases where speed and simplicity are important.

Preserves References: Shallow copy preserves references to the original object or array, which can be useful in certain scenarios where you want to maintain a connection between the original and copied objects or arrays

Cons

Incomplete Copy: Shallow copy only copies the top-level properties or elements of an object or array. This means that any nested objects or arrays are not copied, but instead, their references are copied. This can lead to unintended side e몭ects or changes to the original object or array

Potential for Overwriting: Shallow copy can also lead to the potential for overwriting the original object or array, especially when working with mutable objects or arrays. Any changes made to the shallow copy can also a몭ect the original object or array

Limited Use Cases: Shallow copy is best suited for simple objects or arrays with only top-level properties or elements. For more complex data structures, such as nested objects and arrays or objects with circular references, shallow copy may not be su몭cient

Pros and Cons of Deep Copy

Here are the pros and cons of using deep copy in JavaScript:

Pros

Some of the pros of using deep copy in JavaScript are:

Creates Independent Copies: Deep copy creates completely independent copies of an object or array, which can be useful in cases where you want to avoid unintended side e몭ects or changes to the original object or array.

More Accurate: Deep copy is generally more accurate than shallow copy, since it creates a true copy of all nested objects and arrays. This can be important in cases where accuracy is critical.

Can Handle Complex Objects and Arrays: Deep copy is designed to handle complex objects and arrays, even those with circular references or nested objects and arrays. This makes it useful in scenarios where you’re working with large or complex data structures.

Cons

Some of the cons of using deep copy in JavaScript are:

Slower Performance: Deep copy can be slower and more resource-intensive than shallow copy, especially for large or complex data structures. This can impact the overall performance of your code.

Increased Memory Usage: Deep copy can also lead to increased memory usage, since it creates completely independent copies of all nested objects and arrays This can be a concern for memory-intensive applications.

Di몭culty Handling Circular References: While deep copy is designed to handle circular references, it can still be a challenge to implement in certain scenarios. This can lead to errors or unexpected behavior in your code

Use Cases for Shallow Copy and Deep Copy

Shallow copy and deep copy have di몭erent use cases depending on the speci몭c needs of your code Here are some common scenarios where each method may be more appropriate:

When to Use Shallow Copy

When you need to create a new object or array that shares some of the properties or elements of an existing object or array, but you want to avoid a몭ecting the original object or array

When you need to pass an object or array as a parameter to a function and want to avoid unintended side e몭ects by creating a copy of the object or array.

When you need to quickly create a shallow copy of a small and simple object or array.

When to Use Deep Copy

When you need to create a completely independent copy of an object or array, without any shared references to the original object or array

When you need to make changes to a copied object or array without a몭ecting the original object or array.

When you need to create a deep copy of a large or complex object or array, even if it takes longer than shallow copy

Common Pitfalls and Best Practices

While working with shallow copy and deep copy in JavaScript, there are a few common pitfalls to be aware of, as well as some best practices to follow

Modifying Original Objects or Arrays

One common pitfall when working with shallow copy and deep copy is modifying the original object or array after creating a copy. If you modify the original object or array, the changes will also be re몭ected in the copy, which can lead to unexpected behavior.

To avoid this, you should always make a copy of an object or array before modifying it, and then work with the copy instead of the original.

Performance Considerations

As mentioned earlier, deep copy can be more expensive in terms of performance and memory usage than shallow copy. If you need to create a deep copy of a large or complex object or array, it can take a signi몭cant amount of time and memory

To optimize performance, you should only use deep copy when necessary and try to 몭nd alternative solutions when possible.

Choosing the Right Copying Method

Choosing the right copying method is crucial when working with objects or arrays in JavaScript. If you only need to create a copy of the top-level properties or elements, then shallow copy is the way to go. If you need to create a complete and independent copy of an object or array, then deep copy is the better choice.

Using Libraries and Frameworks

There are many libraries and frameworks available that provide built-in methods for copying objects and arrays in JavaScript. These libraries and frameworks can save you time and e몭ort when working with complex objects or arrays.

Some popular libraries and frameworks for copying objects and arrays in JavaScript include Lodash and Ramda.

Conclusion

In JavaScript, shallow copy and deep copy are two commonly used techniques for copying objects and arrays. While both methods can be useful in di몭erent scenarios, they have their own advantages and disadvantages.

Shallow copy is a faster and more memory-e몭cient method for copying objects and arrays It only creates a new reference to the original object or array, and any changes made to the shallow copy will also a몭ect the original. This makes it a good option for simple data structures with only top-level properties or elements.

On the other hand, deep copy creates a completely independent copy of the original object or array, including any nested objects and arrays. While this method is slower and more memory-intensive than shallow copy, it provides a true copy of the original and can be a better option for more complex data structures

When deciding which method to use, it’s important to consider the speci몭c needs of your application and data structures. In some cases, a combination of shallow copy and deep copy may be the best solution

Overall, understanding the di몭erences between shallow copy and deep copy is an important part of writing e몭cient and e몭ective JavaScript code. By taking the time to carefully consider your options, you can ensure that your code is both performant and easy to maintain

Some related posts about JavaScript:

Best Books to Learn JavaScript (2023)

What is the Use of This Keyword in Javascript?

Lexical Environment in JavaScript

Advantages of Closures in JavaScript

Is TypeScript Faster Than JavaScript?

FAQs

Q: What is the di몭erence between shallow copy and deep copy?

A: Shallow copy creates a new reference to the original object or array, while deep copy creates a completely independent copy of the original, including any nested objects or arrays.

Q: When should I use shallow copy?

A: Shallow copy is a good option for simple data structures with only top-level properties or elements. It is also a faster and more memory-e몭cient option.

Q: When should I use deep copy?

A: Deep copy is a better option for more complex data structures, as it creates a true copy of the original, including any nested objects or arrays.

Q: How do I implement shallow copy and deep copy in JavaScript?

A: Shallow copy can be achieved using or the spread operator ( ), while deep copy can be achieved using and or a custom function that recursively copies the entire object or array.

Q: Are there any performance considerations when using shallow copy and deep copy?

A: Yes, shallow copy is generally faster and more memory-e몭cient than deep copy, but may not be suitable for all data structures It’s important to consider the speci몭c needs of your application when deciding which method to use

Q: Can I use a combination of shallow copy and deep copy in my code?

A: Yes, a combination of shallow copy and deep copy may be the best solution in some cases, depending on the speci몭c needs of your application and data structures.

Object.assign() ... JSON.parse() JSON.stringify() PREVIOUS ARTICLE

Flutter vs React Native: The Ultimate Comparison (2023)

You may also like

useReducer vs Redux: A Detailed Comparison for State Management in React

useReducer vs useState: Choosing the Right React Hook for State Management

Types of Hooks in React: The Ultimate Guide LEAVE

Comment:

Name:*

Email:*

Website: Save

A REPLY
my name, email, and website in this browser for the next time I comment. POST COMMENT
Recent posts

Flutter vs React Native: The Ultimate Comparison (2023)

May 1, 2023

Next JS vs Express: An In-Depth Comparison for Developers

April 29, 2023

WebSocket vs SignalR: An In-Depth Comparison

April 26, 2023

WebSocket vs Webhook: A Comprehensive Comparison Guide

April 22, 2023

Is Flutter Good for Web Development? Here’s What You Need to Know

April 15, 2023

FRONTEND MAG

Discover and share the exciting world of frontend web development to build stunning websites, apps, and services with cutting-edge technologies.

CONTACT

 hello@frontendmag com

 Hanoi, Vietnam

CONNECT

INFORMATION About Contact

Terms and Conditions

Privacy Policy

   
©
Frontend Mag All Rights Reserved
Copyright
2022-2023

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.