Imagine the following array of objects representing individual people.
let people = [
{
name: 'Alice',
age: 19
},
{
name: 'Bob',
age: 32
},
]
You are asked to loop over each object and to add the person's hair and eye color to their object. Fortunately, your task is simplified by the fact that they both have brown hair and hazel eyes. For some reason, you decide to use a property accessor for Alice and a destructuring assignment for Bob. Finally, you log the result.
for (let i = 0; i < people.length; i++) {
let person = people[i];
if (person.name === 'Alice') {
person.hair = 'brown';
person.eyes = 'hazel';
}
else if (person.name === 'Bob') {
let additionalInfo = {
hair: 'brown',
eye: 'hazel'
}
person = { ...person, ...additionalInfo }
}
}
people.forEach(person => console.log(person));
However, the new information is present in Alice's object but not in Bob's!
{ name: 'Alice', age: 19, hair: 'brown', eyes: 'hazel' }
{ name: 'Bob', age: 32 }
Now, I understand why Alice's object gets updated: person.hair = 'brown' get treated as people[i].hair = 'brown' because person === people[i].
I somewhat but not fully understand why this doesn't work with Bob in this example. On one hand, we are reassigning the person variable to something other than people[i], thereby losing the reference, and person is lost after that iteration with no changes made to Bob's object.
On the other hand, my initial expectation was that changes to person would result in changes to people[i] because person === people[i]. Hence it is a little surprising the fix here is to swap out person = { ...person, ...additionalInfo } with people[i] = { ...person, ...additionalInfo }.
Why is this the case? Is it even possible to create a "stable reference" to an object in JS such that changes to the variable containing the reference are applied to the object it is referring to?
person = ...means your are assigning a new value to the local variableperson. That will not affectpeople[i].{}is shorthand fornew Object(). You are creating a new object, and assigning it to the variableperson. So nowpersonis pointing to that new object instead ofpeople[i]a = new X()does not change the content of whatapreviously pointed to but instead assigns the address to a new object to it.