Salaryman
Salaryman

Reputation: 395

Unexpected behavior with Javascript array methods

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

Answers (3)

T.J. Crowder
T.J. Crowder

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

meder omuraliev
meder omuraliev

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

Gonzalo Larralde
Gonzalo Larralde

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

Related Questions