Notice how sherlock.address
is an object. The object { city: 'London' }
.
The code basically assigns the exact same object to john
. So, sherlock
and john
live in the same house, that's fine. But then when john
moves, it assigns Malibu
to the city of his address
, which is the exact same address
object that sherlock
is using, hence sherlock
sees the change.
To fix this, instead of assigning the exact same address object, we need to make a copy.
There are many ways in Javascript to copy an object, but let's use this simple one (the object destructuring/spread operator syntax {...ojb}
):
let john = {
surname: 'Watson',
address: {...sherlock.address}
};
This way, instead of using the object sherlock.address
as is, we copied it. After this, when john
changes his city, it will not reflect to sherlock
.
Another way is to declare an address
object for john
and copy the city, like this:
let john = {
surname: 'Watson',
address: {city: sherlock.address.city}
};
Spread operator vs rest operator, ...
, similar syntax, different purpose:
The Spread operator is used to make a copy of an object, or merge multiple objects together (notice how it is used in the object you want to copy:
const person = {name: "John", lastName: "Doe", age: 59, email: "johndoe@gmail.com"};
const personCopy = {...person};
console.log(personCopy); // {name: 'John', lastName: 'Doe', age: 59, email: 'johndoe@gmail.com'}
// Merging objects:
const moreProperties = {city: "New York", isActive: true};
const merged = {...person, ...moreProperties};
console.log(merged); // {name: 'John', lastName: 'Doe', age: 59, email: 'johndoe@gmail.com', city: 'New York', isActive: true}
The rest operator is used to assign all the properties or the rest of the properties of an object to a variable (notice how it goes in the new variable to you to assign the rest of the properties to):
const person = {name: "John", lastName: "Doe", age: 59, email: "johndoe@gmail.com"};
// Here I'm only extracting the `name` and `lastName` properties of the object into their corresponding variables. Then, I use the rest operator `...` to assign the rest of the properties of `person` that I haven't extracted (copied) into the `restOfTheProperties` (could be named anything) variable, which is essencially a copy of all the remaining properties of the object.
const { name, lastName, ...restOfTheProperties} = person;
console.log(name); // "John"
console.log(lastName); // "Doe"
console.log(restOfTheProperties); // {age: 59, email: 'johndoe@gmail.com'}
It can also be used in function args, like this:
function etc(...args) {
console.log(args);
}
etc(1,2,3); // [1,2,3]
Could be used for arrays too.
More info here: https://www.freecodecamp.org/news/javascript-rest-vs-spread-operators/