Stop Making This Mistake: Shallow vs. Deep Cloning in JavaScript

If you've ever changed a property in a "copied" object only to find that the original object changed too, you’ve been bitten by the "Shallow Clone" bug.
In JavaScript, understanding the difference between Shallow and Deep clones is the difference between writing predictable code and spending your Friday night debugging "ghost" mutations. Let’s dive in.
The Core Concept: Reference vs. Value
Before we look at code, remember one thing:
Primitives (Strings, Numbers, Booleans) are copied by Value.
Objects and Arrays are copied by Reference (they point to a spot in memory).
1. What is a Shallow Clone?
A shallow clone creates a new object, but it only copies the top-level properties. If your object contains another object (nested data), the clone will still point to the same memory address as the original.
Using the Spread Operator (...)
This is the most modern and common way to shallow clone.
const origObj1 = {
name: "John",
address: { city: "Bhopal" }
};
const cloneObj1 = { ...origObj1 };
// Changing a top-level property (No problem!)
cloneObj1.age = 24;
// Changing a nested property (DISASTER!)
cloneObj1.address.city = "Indore";
console.log(origObj1.address.city); // Prints "Indore" - The original changed!
Using Object.assign()
This is the "classic" way to do it. It behaves exactly like the spread operator.
const origObj2 = {
name: "John Doe",
education: { almameter: 'HFC' }
};
const cloneObj2 = Object.assign({}, origObj2);
cloneObj2.education.almameter = "RITS";
console.log(origObj2.education.almameter); // Prints "RITS"
2. What is a Deep Clone?
A deep clone is a total "breakup." It recursively copies everything, including nested objects. The two objects become 100% independent.
The Modern Way: structuredClone()
Introduced recently to the browser and Node.js, this is now the gold standard for deep cloning.
const origObj3 = {
name: "Joe Doe",
metadata: { sport: "cricket" }
};
const cloneObj3 = structuredClone(origObj3);
cloneObj3.metadata.sport = "football";
console.log(origObj3.metadata.sport); // Prints "cricket" - Safe!
console.log(cloneObj3.metadata.sport); // Prints "football"
The "Old School" Hack: JSON.parse(JSON.stringify())
Before structuredClone, we used this trick. It works for simple data but has huge drawbacks:
It deletes Functions.
It turns Dates into strings.
It fails on Circular References.
| Feature | Shallow Clone (...) | Deep Clone (structuredClone) |
| Independence | Only for top-level properties | 100% Independent |
| Performance | Extremely Fast | Slower (Recursive) |
| Shared References | Yes (for nested objects) | No |
| Best Use Case | Flat objects, React State | Complex datasets, Redux |
Which one should you use?
Use Shallow Clones when your data is "flat" or when you are updating state in frameworks like React where you only need to change a top-level key.
Use Deep Clones when you are dealing with complex configurations or nested arrays/objects that you need to modify without side effects.




