Javascript pointer/reference craziness. Can someone explain this?

Philip Walton picture Philip Walton · Nov 29, 2011 · Viewed 24k times · Source

Javascript passes objects by reference. This makes perfect sense. But once you start manipulating those objects, everything acts in a way that seem unintuitive. Let me offer an example:

var a, b;

a = {}
b = a;
a['one'] = {};

console.log( JSON.stringify(a) );
// outputs: {"one":{}}

console.log( JSON.stringify(b) );
// outputs: {"one":{}}

This is all well and good because now b has a pointer to a so it's expected that assigning stuff to a will also affect b.

But then if I do this:

a = a['one'];

console.log( JSON.stringify(a) );
// outputs: {}

console.log( JSON.stringify(b) );
// outputs: {"one":{}}

This is surprising to me. I'd expect a and b to still be the same (and to be {} since a['one'] was previously set to {} and a was set to a['one']).

But that's not the case. It appears that a loses its reference to b when it's assigned to something new, but b maintains the value that a was set to prior to a loosing its reference to b.

But then if I do this:

a['two'] = 2;

console.log( JSON.stringify(a) );
// outputs: {"two":2}

console.log( JSON.stringify(b) );
// outputs: {"one":{"two":2}}

What? a has clearly lost it's reference to b, but b seems to still have some reference to a.

Does the empty object {} point to some place in memory so every variable referencing it is now pointing to the same place?

Can someone with a firm grasp on this explain it to me?

Answer

Seth Carnegie picture Seth Carnegie · Nov 29, 2011

Following your example line by line:

a = {}

a now references the new object.

b = a;

b now references the same object that a references. Note that it does not reference a.

a['one'] = {};

The new object now has an index 'one' that references another new object.

When you do

a = a['one'];

You are setting a to refer to a['one'], which is that new object you created when you did a['one'] = {}. b still references the object you created with a = {}.

You are confusing the issue when you say "a has lost its reference to b" because a does not refer to b , nor vice versa. a and b refer to objects, and they can be made to refer to other objects. Like this:

With a = {}; b = a, you get

a
 \
  \
   { }
  /
 /
b

Then with a['one'] = {} you get

a
 \
  \
   { one: { } }
  /
 /
b

Then with a = a['one'] you get

a - - - - 
          \
   { one: { } }
  /
 /
b