In JavaScript, objects are mutable. This means if you assign an object to a new variable, both variables refer to the same memory. Any change made through one will affect the other.
Let's explore what this means β and how to avoid unintended side effects using techniques like shallow copy, deep copy, and Immer.
π Problem: Object Mutability
const employee = {
name: "Mir",
address: {
country: "Bangladesh",
city: "Dhaka",
},
};
const employee2 = employee;
employee2.name = "Mezba";
console.log(employee.name); // "Mezba" β Unexpected mutation
employee2
andemployee
point to the same object. Changingemployee2
affectsemployee
.
π§ͺ Solution 1: Shallow Copy with Spread Operator
const employee2 = {
...employee,
name: "Mezba",
};
employee2.address.city = "Chittagong";
console.log(employee.address.city); // "Chittagong" β still mutated!
This only copies the top-level fields β nested objects like
address
are still shared.
π Solution 2: Manual Deep Copy (One Level Down)
const employee2 = {
...employee,
name: "Mezba",
address: {
...employee.address,
city: "Chittagong",
},
};
console.log(employee.address.city); // "Dhaka" β
We manually copy nested structures to break the shared reference.
π§± Solution 3: Structured Clone (Modern Browsers)
const employee2 = structuredClone(employee);
employee2.name = "Mezba";
employee2.address.city = "Chittagong";
console.log(employee.address.city); // "Dhaka" β
structuredClone()
performs a deep copy automatically.
β οΈ Browser support: Modern browsers only (Chrome 98+, Node.js 17+)
π οΈ Solution 4: Deep Copy Using Immer
Immer lets you write mutative code that produces immutable updates.
π§ Step 1: Install Immer
npm install immer
π¦ Step 2: Use produce
to Make Safe Updates
import { produce } from "immer";
const employee = {
name: "Mir",
address: {
country: "Bangladesh",
city: "Dhaka",
},
};
const employee2 = produce(employee, (draft) => {
draft.name = "Mezba";
draft.address.city = "Chittagong";
});
console.log(employee);
// Output: { name: 'Mir', address: { country: 'Bangladesh', city: 'Dhaka' } }
console.log(employee2);
// Output: { name: 'Mezba', address: { country: 'Bangladesh', city: 'Chittagong' } }
β Clean, concise, and powerful. Perfect for managing immutable state in tools like Redux.
π Summary Table
Technique | Type | Handles Nested? | Notes |
---|---|---|---|
... spread |
Shallow Copy | β | Only copies top-level |
Manual nested spread | Partial Deep | β (Manual) | Tedious for deep structures |
structuredClone() |
Deep Copy | β | Browser/Node support required |
Immer (produce ) |
Deep Copy | β | Cleaner syntax for immutable logic |
π§ Final Thoughts
- Use shallow copy for flat objects.
- Use structuredClone or Immer for deeply nested updates.
- Immer is especially useful in React state management scenarios where immutability is key.
This post was crafted with a little help from AI π€
βοΈ If you found this helpful, feel free to share or comment below. Happy coding!
Top comments (0)