The confusing thing about objects is that PRIMITIVES behave differently to OBJECTS
When you "read" a primitive string (or number or Boolean), such as sherlock.surname
, you are taking the value of it, i.e. you are receiving a copy of the original data. So if you do
eureka = {surname: sherlock.surname}
then you can think of eureka
receiving a "photocopy" of the original "Holmes". There will be two strings "Holmes" stored in your computer. You can change one, and the other will not change, because they are separate.
But when you "read" an object, such as sherlock
, you should imagine that you are taking only a pointer to the original object. Not a copy of it, but another path through the computer to reach the same memory location. So if you do
eureka = sherlock
then this statement does not create a second copy of the string "Holmes" inside the computer. There is only one "Holmes" string in the memory of the computer. It is inside an object like this: {surname: "Holmes"}
. sherlock
points to that object, and eureka
points to the same object. Therefore, when you edit some property of eureka
or sherlock
, the corresponding properties of both variables will have changed simultaneously. The two variable names, eureka
and sherlock
, are pointing to the same object in memory.
The above is quite elementary (excuse my pun!) but where it gets tricky is when you are referencing an object-within-an-object, or a primitive-within-an-object. Looking at the assignment statement alone you cannot tell whether the thing you are reading is a primitive or an object. You must know the structure in order to know.
let a={b:{c:1}}
let w = a // This makes "w" an alias for the same single object, to which "a" also points
w.b.c=2
console.log(a)
// {
// "b": {
// "c": 2
// }
// }
w.b = 3
console.log(a)
// {
// "b": 3
// }
Annotating your script here
let sherlock = {
surname: 'Holmes',
address: { city: 'London' }
};
let john = {
surname: 'Watson',
address: sherlock.address // Here, you are not COPYING the { city: 'London'}, you are pointing at the same object in memory, i.e. the "address" property of sherlock.
};
john.surname = 'Lennon';
john.address.city = 'Malibu'; // When you go to john.address, you are now pointing into the piece of memory that sherlock is also using to store his address, so when you put a value into 'city', that will show up whether you access it as john.address or sherlock.address
console.log(sherlock.address.city);