I know this works, but I don't know why or the reasoning behind why it was made to work this way:
var foo = [5, 10];
var bar = foo;
console.log(foo); //[5, 10]
console.log(bar); //[5, 10]
bar[0] = 1;
console.log(foo); //[1, 10]
bar = null;
console.log(foo); //[1, 10]
I would have expected not just bar
to become null, but foo
as well. I'd love some help understanding this.
The difference is between rebinding and mutating operations.
bar[0] = 1
is mutating; it affects the object that bar
points to.
bar = null
is rebinding; it just affects what the identifier bar
means.
When you do bar = null;
that just assigns something to the value of the bar
variable. It does not affect what used to be assigned to bar
. That object continues to live on and if there are other references to it, it stays alive with its value untouched.
When you do this:
var foo = [5, 10];
var bar = foo;
You have three entities. You have an array [5,10]
and two variables each with a reference to that array. If you change the array, then since both variables point to the same array, you will see that change no matter which variable you reference the array through.
But, if you set bar = null
, that just affects the bar
variable which then no longer has a reference to the array. It doesn't affect the array at all which is still pointed to by foo
.
In fact, if you did this:
var foo = [5, 10];
var bar = foo;
bar = [20,30];
You'd have the same sort of result. After the second line of code both bar
and foo
pointed to the same array, but after the third line, bar
now points to a new array and only foo
points to the original array. The key is realizing that there's a difference between using bar
to modify the object it points to as in bar[0] = 1
versus reassigning the whole value of bar as in bar = [20,30]
. In the first case, the underlying object that both foo
and bar
point to is changed. In the second case, the underlying object that bar
originally pointed to is not touched. Instead, bar
is changed to point a new object and the prior object is not touched.
You have two pointers to the array. Bar = foo copies the original pointer. Dereferencing bar does not dereference foo.
Read more @
http://snook.ca/archives/javascript/javascript_pass
Reference, but it's definition is just a pointer to some object. When you assign null
to bar, you simply delete this "pointer" that was stored in bar
, making it no longer point to object.
Imagine this as an address, written on sheets of paper. If sheet foo
and bar
have same address on it and you issue a command: go to address written on sheet foo
and put something in house there, after operation is done, naturally, whoever looks at any of those sheets and checks out that address, will find those changes. Now your assignment of null
is just same as wiping this address from sheet with eraser. It doesn't touch neither any other sheets, nor house in any way.
I like to think of variables as labels. Makes explaining them easier.
//Create an array containing 5 and 10, and put the label "foo" on it
var foo = [5, 10];
//Put the label "bar" on the thing with the label "foo"
var bar = foo;
console.log(foo); //[5, 10]
console.log(bar); //[5, 10]
//Take the thing labeled "bar" (which also has the label "foo") and change the first element to 1
bar[0] = 1;
console.log(foo); //[1, 10]
//Take the label "bar" and attach it to nothing
bar = null;
console.log(foo); //[1, 10]
var foo = [5, 10];
var bar = foo;
console.log(foo); //[5, 10]
console.log(bar); //[5, 10]
bar[0] = 1;
console.log(foo); //[1, 10]
bar = null;
console.log(foo); //[1, 10]
When you do
var foo = [5, 10];
It creates a reference to an array, like this
foo ---> [5, 10]
When you assign bar
to foo
, you now have
foo ---> [5, 10]
bar ------^
When you call
bar[0] = 1;
you get
foo ---> [1, 10]
bar ------^
where foo
and bar
point to the same object.
When you call
bar = null;
you now have
foo ---> [1, 10]