DEV Community

Salman Sadi
Salman Sadi

Posted on

Why Mutating an Object Returned by Array.find() Changes the Original Array

JavaScript objects don’t behave the way many people expect. Can you guess what the output of the following code?


const users = [
  { id: 1, name: "John" },
  { id: 2, name: "Jane" }
];

const foundUser = users.find(u => u.id === 1);

foundUser.name = "Updated John";

console.log(users);

Enter fullscreen mode Exit fullscreen mode

✔ The output of the code above will be:

[
 { id: 1, name: "Updated John" },
 { id: 2, name: "Jane" }
]
Enter fullscreen mode Exit fullscreen mode

This surprises many people, but it is completely expected behavior in JavaScript.

🤔Why this happens?
→ Arrays in JavaScript store references to objects
→ Array.find() returns the actual object, not a copy
→ Objects are reference types, not value types

So after this line:
const foundUser = users.find(u => u.id === 1);

👉 Both of these point to the same object in memory:

users[0] ────┐
 ├──► { id: 1, name: "John" }
foundUser ───┘ 

Enter fullscreen mode Exit fullscreen mode

👉 When you do:
foundUser.name = "Updated John";

You are mutating that shared object.
Since the array holds a reference to the same object, the array reflects the change.

💡 A safer approach is to update immutably (create a new array and a new object):

const updatedUsers = [];

const updatedUsers = users.map(user =>
 user.id === 1 ? { ...user, name: "Updated John" } : user
);
Enter fullscreen mode Exit fullscreen mode

▶ But remember: { ...user } is a shallow copy. If user contains nested objects, those nested references are still shared. In that case, you must copy the nested structure you modify, or use a deep clone.

▶ There is another option which is called structuredClone().
This function returns a deep copy of the object you are passing as an argument.

const copy = structuredClone(user);
Enter fullscreen mode Exit fullscreen mode

Now mutating copy won’t affect the original object.

Top comments (0)