I was playing with chrome console and noticed something which I couldn't understand. I know in JS variables are copied by value and objects are copied by reference. Below code works fine as expected which outputs 2 and proves JS objects work as reference:
var objA = {a: 1};
var objB = objA;
objA.a = 2;
objB.a; // 2
However this code doesn't work as it should. I expected objB.a to output 2
but it gives 1
instead. Why?
var objA = {a: 1};
var objB = objA;
objA = {a: 2}; //Assigned whole object here instead property.
objB.a; //1 - Shouldn't this be 2 ??
I'd rather think of variables with objects as pointers to objects (like C pointers) rather than references.
In your third line, you just replaced objA
, making it "point to" another object. It does not change whatever objB
is "pointing".
By line 3, objA
now points to {a:2}
while objB
still points to whatever objA
was pointing at the time you assigned it to objB
, at line 2, which is {a:1}
.
line 1: objA -> {a:1}
line 2: objA -> {a:1} <- objB
line 3: objA -> {a:2}, objB -> {a:1}
I like to think of JavaScript variables as sticky notes. A sticky note is a small note which you put on your fridge. What can you write on your sticky note? You can write small pieces of information.
Now there are two types of information in JavaScript - primitive values and reference values. Primitive values are small pieces of information that you can write on your sticky note directly. They include:
On the other hand reference values are large amounts of information which you can't write on a small sticky note. So how do you store reference values in sticky notes?
You don't.
Reference values (like arrays, objects and functions) are written on a bigger piece of paper and only a reference to them is written on the sticky note. For example, my wife might write:
Honey, the list of groceries is under your keyboard.
Here the list of groceries is an array (i.e. a large amount of information). Since we can't write it on a small sticky note we simply write it on a bigger piece of paper and make a sticky note which tells us where it is to be found. In programming terms:
var groceryList = ["1 apple", "2 bananas", "3 loaves of bread"];
Here the actual grocery list is stored somewhere in memory and only the address of the grocery list is stored in the variable groceryList
.
So what happens when we assign one variable to another? Let's first take an example of a primitive value:
var x = 2;
var y = x;
alert(y); // 2
y = 3;
alert(x); // 2
This is what's happening:
2
on a new sticky note and put it on our fridge.2
from the sticky note x
onto another sticky note y
and put it on our fridge.y
and write the number 3
on it instead.x
is 2
and sticky note y
is 3
.This is called copy by value because we're just copying the value of sticky note x
onto sticky note y
.
Now let's take an example of copy by reference. In fact let's take your example of copy by reference:
var objA = {a: 1};
var objB = objA;
objA.a = 2;
objB.a; // 2
Here's what's happening in your example:
{a: 1}
somewhere in memory and write the address of this object on sticky note objA
. Let's call this address x
for simplicity's sake.x
from sticky note objA
onto another sticky note objB
. Now both objA
and objB
reference the same object {a: 1}
stored at memory location x
.objA.a
the same change is reflected on objB.a
because objA
and objB
both reference the same object stored at memory location x
.This is called copy by reference because we are simply copying the reference of an object from sticky note objA
to sticky note objB
. We're not copying the actual object.
So what's the difference between copy by reference and copy by value? Absolutely nothing. In both cases we're simply copying the value of one sticky note onto another.
Two sticky notes are said to be equivalent only when they contain the exact same information. For example the following are equivalent:
var x = 2;
var y = 2;
alert(x === y); // true
var o = {a: 1};
var p = o;
alert(o === p); // true
However the following values are not equivalent:
var o = {a: 1};
var p = {a: 1};
alert(o === p); // false
The reason that they are not equivalent is because o
points to an object stored at a memory location say x
while p
points to an object stored at a different memory location say y
. Although both these objects have the exact same properties they are in fact two different objects.
For example no two Nintendo Gameboys are the same no matter how identical they look. In the same spirit let's take a look at your last example:
var objA = {a: 1};
var objB = objA;
objA = {a: 2}; //Assigned whole object here instead property.
objB.a; //1 - Shouldn't this be 2 ??
Here's what happening in the above code:
{a: 1}
at a memory location x
and write the address x
on a sticky note objA
.x
from sticky note objA
to sticky note objB
. Both of them now point to the same object stored at memory location x
.{a: 2}
at a memory location y
and write the address y
on the stick note objA
. Now objA
has a reference value y
and objB
has a reference value x
. They reference two different objects.As you can see assigning a new reference value to objA
simply overwrites the old reference value. It does not replace the object {a: 1}
with the object {a: 2}
. That's not possible in JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With