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.