Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS object copy by value vs copy by reference

Tags:

javascript

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 ??
like image 778
RuntimeException Avatar asked Oct 18 '13 11:10

RuntimeException


2 Answers

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}
like image 138
Joseph Avatar answered Oct 09 '22 17:10

Joseph


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:

  1. Booleans
  2. Numbers
  3. Strings
  4. Null
  5. Undefined

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:

  1. We write the number 2 on a new sticky note and put it on our fridge.
  2. We copy the number 2 from the sticky note x onto another sticky note y and put it on our fridge.
  3. We erase the value of sticky note y and write the number 3 on it instead.
  4. Now the value of sticky note 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:

  1. We create an object {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.
  2. We copy the address 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.
  3. Hence when we change the value of 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:

  1. We create an object {a: 1} at a memory location x and write the address x on a sticky note objA.
  2. We copy the address x from sticky note objA to sticky note objB. Both of them now point to the same object stored at memory location x.
  3. We create a new object {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.

like image 31
Aadit M Shah Avatar answered Oct 09 '22 16:10

Aadit M Shah