Shallow Copy vs Deep Copy in JavaScript: A Common Confusion I Faced While Interviewing a Candidate!
Photo by KOBU Agency on Unsplash
During a recent interview with a candidate, we got into an interesting discussion about shallow copy and deep copy in JavaScript. Initially, I thought I had a solid understanding of the concept, but the candidate’s response made me stop and think for a moment. 🤔
They said, “Shallow copy does copy the reference!” which made me wonder if I might be missing something.
After reflecting on it, I want to clarify this common confusion and share my understanding of how shallow and deep copies actually work.
Shallow Copy in JavaScript
A shallow copy creates a new object with the top-level properties duplicated (i.e., primitive values like strings, numbers, booleans, etc.). However, when it comes to nested objects or arrays, the shallow copy copies the reference to those nested values instead of duplicating the entire object.
So, any changes made to the nested objects/arrays in the shallow copy will affect the original object.
Shallow Copy Example
Here’s an example to demonstrate how shallow copy works:
const obj1 = { name: "Roja", birthDate: new Date(), details: { city: "Chennai" } };
const obj2 = { ...obj1 }; // Shallow copy
obj2.name = "John"; // Independent change
obj2.details.city = "Bangalore"; // Mutates obj1
obj2.birthDate.setFullYear(2025); // Mutates obj1's birthDate as well
console.log(obj1.details.city); // "Bangalore" (mutated!)
console.log(obj1.birthDate.getFullYear()); // 2025 (mutated!)
What happened here?
obj2.name
= "John"
: This worked fine! Sincename
is a primitive value, it was copied and changes didn't affectobj1
.obj2.details.city
= "Bangalore"
: This changed bothobj2
andobj1
, because thedetails
object is nested, and the shallow copy only copies the reference, not the object itself.obj2.birthDate.setFullYear(2025)
: This also modified the originalobj1
object, asbirthDate
is an object (of typeDate
), and its reference was copied in the shallow copy.
When to Use Shallow Copy?
Shallow copy works great for top-level properties where there are only primitive values. But for complex, deeply nested objects or arrays, using shallow copy can lead to unintentional mutations in the original object, as seen in the example above.
How to Make a True Deep Copy in JavaScript
If you need to fully duplicate an object, including nested objects, and avoid shared references, you'll need to use deep copy techniques.
Deep Copy Methods in JavaScript
1. structuredClone()
(Modern Approach)
structuredClone()
is a built-in JavaScript function that creates a true deep copy of an object. It works with modern browsers and handles more complex data types, including Date
, Map
, Set
, and RegExp
.
const obj2 = structuredClone(obj1); // Deep copy
2. JSON.parse(JSON.stringify())
(For Simple Objects)
This method serializes the object into a JSON string and then deserializes it back into a new object. It works for simple objects but does not handle special data types like Date
, functions, or non-enumerable properties
const obj2 = JSON.parse(JSON.stringify(obj1)); // Deep copy
3. lodash.cloneDeep()
(For Complex Objects)
lodash.cloneDeep()
is a third-party utility from the popular Lodash library. It creates a deep copy of an object and handles edge cases like circular references, as well as special objects like Date
and Map
.
const obj2 = lodash.cloneDeep(obj1); // Deep copy
Which Method Should You Use?
structuredClone()
is the most modern and handles complex data types, but it’s only supported in newer browsers.JSON.parse(JSON.stringify())
is a simple and lightweight method but should be avoided if you're working with complex objects likeDate
or custom functions.lodash.cloneDeep()
is the most robust solution for complex objects, handling all edge cases, including circular references and special types.
Key Takeaways:
Shallow Copy: Duplicates top-level properties but copies the reference for nested objects/arrays. Changes to nested objects affect the original.
Deep Copy: Creates a fully independent copy of the object, including nested objects, ensuring no shared references.
Use
structuredClone()
for modern use cases,JSON.parse(JSON.stringify())
for simple objects, andlodash.cloneDeep()
for complex objects.
Conclusion
This interview discussion made me realize how important it is to fully understand the difference between shallow and deep copies, especially when working with objects in JavaScript. It’s always a great learning experience to revisit core concepts like these.
Have you faced any similar moments of confusion or learning during interviews or while coding? Feel free to share your thoughts or experiences in the comments below!
Let’s keep learning together! 💬