This is not new to many but I’ve always been curious about it:
Why does the following happen?
var a:Array = [1, 2, 3];
var b:Array = a;
b.push(4);
trace(a); // 1,2,3,4
I discovered that this behavior is much more “extensive” than I thought in a current project where I have an object whose parameters include arrays. I saw what I thought was very odd behavior, then reproduced the problem in simplistic form, below:
var foo:Array = [1, 2, 3];
var obj:Object = {param:foo};
var bar:Array = obj.param;
trace("bar = " + bar); // bar = 1,2,3
bar.push(4);
Is there a name for this behavior? And either way, WHY does Actionscript behave this way? (I’m not a programmer so I don’t have experience with other languages, so I also wonder if this array behavior is common to other languages as well.)
BTW I am aware that the slice method can be used to “independently” duplicate an array.
I’m typing on my phone and driving in fog so this will be brief and dangerous. When an array is created through square brackets or new Array, a chunk of memory at a specific location is set aside to store its data. Then when it is assigned to a variable, the variable points to that specific location. So in your first example, a and b both point to the same location and therefore the same array. Does that make sense?
It saves memory. Any complex object (non-primitive) is stored in variables as references. Imagine what would happen if they weren’t and you decided to store root to another variable. That would require your entire movie to be copied - all values and functions and other definitions - and stored in that variable. As a reference, its just a single value of <where-to-find-this-pre-existing-value-in-memory>. Same applies to arrays. Arrays can be small, but they can also be big. There’s no reason to copy an array if you don’t need to. And if you do, you can do that as well, but by default, the approach is the one that saves on memory.
Because it’d be super annoying if it were the default behavior that a didn’t receive updates performed on b, because you used the assignment operator to say they’re the same thing. For arrays in particular, that’s why the Array class’s methods differ so much about whether or not they return a copy or mutate the original. Whoever designed the API made a decision about what people would expect to be the “right” behavior for each method. splice and concat return copies, but pop and unshift don’t.
It’s usually called the reference model of variables, although people more commonly talk about the case of what happens if you pass (say) an array into and out of a function. Then AS3 falls into the call by sharing evaluation strategy.
It’s mostly because other languages, especially JavaScript, do it that way. ActionScript 1-3 were closely related to the standard which governs JavaScript. But JavaScript does it that way because of the reasons that TC, sen, and I mention above.
It’s also more awkward to design a language that copies by default and has options to use a reference. You’re all but required to introduce a referencing syntax like C/++'s * and & if you want to avoid being ridiculously verbose.
[hr][/hr]
Also if you religiously enjoy avoiding mutation, you end up with a language as usable as Haskell.
Yep, totally a valid question. And since the three of us replied, you can tell it’s more interesting than a lot of the other questions we see around here.