You want to copy an array, but y ou want the duplicate to be dissociated from the original array.
Use the concat( ) method or the slice( ) method.
Because arrays are a composite datatype, they are copied and compared differently from primitive data. A variable that holds an array doesn't truly contain all of the array's data. Instead, the variable simply points to the place in the computer's memory where the array's data resides. This makes sense from an optimization standpoint. Primitive data tends to be small, such as a single number or a short string. But composite data, such as an array, can be very large. It would be very inefficient to copy an entire array every time you wanted to perform an operation on it or pass it to a function. Therefore, when you try to copy an array, ActionScript doesn't necessarily make a separate copy of the array's data. A simple example illustrates this.
First, let's look at how primitive data is copied from the variable myNumber to another variable, myOtherNumber:
// Assign the number 5 to a variable. var myNumber = 5; // Copy myNumber's value to another variable, myOtherNumber. var myOtherNumber = myNumber; // Change myNumber's value. myNumber = 29; trace(myNumber); // Displays: 29 trace(myOtherNumber); // Displays: 5
When the copy is made, the contents of myNumber are copied to myOtherNumber. After the copy is made, subsequent changes to myNumber have no effect on myOtherNumber because primitive data is said to be copied by value.
Now, let's look at an analogous operation with arrays, but note the substantial difference from the preceding example. Data is copied from the variable myArray to the variable myOtherArray, but the two variables remain joined! When the value of myArray changes, the changes are reflected in myOtherArray!
// Assign elements of an array. var myArray = ["a", "b", "c"]; // Copy myArray to another variable, myOtherArray. var myOtherArray = myArray; // Both arrays contain the same values, as expected. trace(myArray); // Displays: "a,b,c" trace(myOtherArray); // Displays: "a,b,c" // Change myArray's value. myArray = ["d", "e", "f"]; // Surprise! Both arrays contain the new values. The old values are lost! trace(myArray); // Displays: "d,e,f" trace(myOtherArray); // Displays: "d,e,f" (not "a,b,c")
Is the relationship between two copies of an array a good thing or a bad thing? The answer depends on what you expect and what you need to accomplish. Let's first understand what is happening, then learn how to address it.
In the preceding example, the following line does not make a copy of myArray's contents, as it would if myArray held a primitive datum:
var myOtherArray = myArray;
Instead, it says to Flash, "Make myOtherArray point to whatever myArray points to, even if the contents change in the future." So the two variables myArray and myOtherArray always point to the same data in memory. If it helps, you can think of this arrangement as being similar to a file shortcut on Windows (which is called an alias on the Macintosh). A shortcut simply points to another file located elsewhere. Whether you open the original file directly or access it via the shortcut, there is only one physical file that contains the content of interest. If the file's contents change, the shortcut still offers access to the current contents of the file. If you wanted two independent files, you'd have to duplicate the original file rather than simply create a shortcut to it.
So, is it a good thing if two arrays refer to the same data? As explained earlier, in the natural course of things, it increases efficiency to avoid copying the contents of an array unnecessarily. But you might wish to operate on a copy of an array so as not to alter the original. For example, in Recipe 5.10, we set up a deck of cards as an array and make a copy of it before dealing. That way, when we want a new deck, we can easily make a new copy from the pristine original without having to recreate it from scratch.
You can create a copy of an array that is separate from the original using concat( ):
// Assign elements of an array. var myArray = ["a", "b", "c"]; // Create an independent copy of myArray using concat( ), which returns a new array. var myOtherArray = myArray.concat( ); // Both arrays contain the same values, as expected. trace(myArray); // Displays: "a,b,c" trace(myOtherArray); // Displays: "a,b,c" // Change myArray's value. myArray = ["d", "e", "f"]; // Unlike preceding examples, the arrays are independent. trace(myArray); // Displays: "d,e,f" trace(myOtherArray); // Displays: "a,b,c"
In line 4 of the preceding example, you could also use slice( ) instead of concat( ), as follows:
var myOtherArray = myArray.slice(0);