Think of it this way. a[0]
is not the actual object {x : 1}
. That object is somewhere in memory, and a[0]
holds the memory address where that object is stored.
If you do a[0].x
you dereference it. That means that you analyze the part before the .
and see the address. You then fetch the object at that address and see if it has a property x
and return it.
But if you do b=a[0]
you're basically just copying the address of the object into b. So now you have two references (shortcuts to the memory address were the object is stored). If you now do b.x = 5
you look at what's before the .
; it's b
containing the address of the object, you fetch that object from memory, check if it has property x
and change its value to 5. But a[0]
points at the same address (so at the same object) so if you try to do a[0].x
like before, you arrive at the address you just modified.
This is a bit of a simplified explanation, but you should think of variables holding objects as shortcuts to the memory address where the actual object is. And if you try to assign a variable the value of another object variable, your just making a new shortcut. This isn't true for variables holding numbers, so x actually holds the value 1
, or 5
, not an address. So if you do:
y = a[0].x;
y = 10;
a[0].x
will not change its value .