Reputation: 395
Take the following code
var a = b = [];
a.push('value');
if (a === b) {
console.log('a === b'); // this will execute
}
console.log(a, b); // ["value"] ["value"]
What gives? Why are both a
and b
modified? Is the var
declaration making b
a live copy of a
? If so, then how come the same cannot apply for regular variable assignment such as:
var a = b = '';
a = 'value';
if (a === b) {
console.log('a === b'); // this will never run
}
console.log(a, b); // value
Of course, using the following declaration solves the problem in the initial example:
var a = [], b = [];
But the behavior in the initial example struck me as odd, especially that it only applies to array operations.
If it helps, I'm using Google Chrome 10.0.648.82 beta
Upvotes: 0
Views: 349
Reputation: 1074058
When you store "an object" (including an array) in a variable, what you're really storing is a reference (or "pointer") to the object, not a copy of the object itself. That is, the object exists somewhere in memory, and what's stored in the variable is a piece of information that tells the interpreter where to find that object.
In contrast, primitives like numbers or booleans are actually stored in the variable.
So in my best ASCII art, when you have the code
var y = [];
...you end up with this:
+−−−−−−−−−−+ | y | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−+ | Ref55467 |−−−−−−−−−−−>| The actual array | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−+ | [] | +−−−−−−−−−−−−−−−−−−+
(Obviously, the Ref55467
is just an example, and you can never actually see the object reference's underlying value in code.)
...whereas with:
var x = 32;
...you end up with:
+−−−−−−−−−−+ | x | +−−−−−−−−−−+ | 32 | +−−−−−−−−−−+
Now let's look at your
var a = b = [];
That looks like this:
+−−−−−−−−−−+ | a | +−−−−−−−−−−+ | Ref55467 |−−−−−−+ +−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−−+ +−−−−>| The actual array | | +−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | [] | | b | | +−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | Ref55467 |−−−−−−+ +−−−−−−−−−−+
Both a
and b
reference (point to) the same array in memory, and so operations that change the array, change the array, regardless of which reference you invoke them on.
In contrast with:
var a = b = 32;
....which looks like:
+−−−−−−−−−−+ | a | +−−−−−−−−−−+ | 32 | +−−−−−−−−−−+ +−−−−−−−−−−+ | b | +−−−−−−−−−−+ | 32 | +−−−−−−−−−−+
The number 32 is actually stored in each place, rather than being in a central place both variables point to.
This is also true when you pass values into functions. With an object reference, the value you're passing into the function is an object reference. You're not actually passing the object into the function, just a reference to it. And that means if the function uses the reference to operate on the object, you see the result in the calling code. Example:
function foo(theArray) {
theArray[0] = 1;
}
var a = ["one", "two", "three"];
foo(a);
alert(a[0]); // alerts "1"
When we called foo
, we passed in a reference to the array object, and so when foo
used that to modify the array, we see the result.
Upvotes: 4
Reputation: 186562
The concept you need to grok is referencing. When you assign a variable to another one which points to an object ( []
, new Array
, {}
, new Object
, functions, and so forth ) in ECMAScript, the reference is passed. b
will refer to a
unless you create a new object and assign it to b
.
To reiterate, var a = [], b = []
creates two distinct arrays. var a = b = []
assigns b
to []
and then b
to a
which picks up the same exact object stored in memory. Any mutator methods will mutate that object and any variables assigned to that object will refer to that object.
Upvotes: 6
Reputation: 3541
It's not a live copy, it's an object referencing to the same instance.
When you run []
you're doing new Array()
, so, you're assigning the new Array
instance to a
and b
.
Good luck!
Upvotes: 2