Array


Array is a Class extended from Object. It gets many methods in addition to the generic Object, but still has the properties of object.

Lets peek some of interesting aspects of the properties.

1. Array.length;

The single most important property is Array.length. Array.length is created when the Array is initialized. It is not Array.length(), so the length is just a value maintained by System. When we want to know Array.length, system give us that value directly. This means that, system does not check the content of Array to calculate the length. Array.length is accessed and modified if we add elements to it. It is also accessed and modifed by many methods of Array, like splice, push, pop etc. The interesting point is that, we can "change" Array.length freely. Since pop and push access Array.length to do operation, system will be mis-guided and the result will be interesting.

//exp 1: 
a=[0,1,2,4,5];
a[-1]=6;

trace(a);
trace(a[-1]);


Well, we can access a[-1] without problem. However, it is illegal. To say a[-1] turns out to be Object method, something like a["mine"];Since Array is extended from Object, it is also an object and we can use that syntax to add a property well. However, property name should follow the naming convention and a pure number is not a good one.

Here we understand how trace works for an array. It just loop from index 0 to Array.length-1, not dumping all contents in this Object. We can find the a[-1] in debug-view Variable, but will not see it when we trace array.

Note that, the Array.length does not change because of the added element a[-1];

//exp 2:
a=[0,1,2,3,4];
a[6.5]=6.5;

trace(a.length);
trace(a);
trace(a[6.5]);


This code is still illegal, although a[6.5] is accessible. 

When an element is added, it compare the index with Array.length and then update the Array.length if necessary. The added element has index 6.5, so it update the Array.length to 7; However, when we trace the content of Array, it dump from a[0]......to a[6]; Of-course, there is no a[5] and a[6]. Only a[6.5];

//exp 3:
a=[0,1,2,3,4];
delete a[4];

trace(a.length);
trace(a);


Only Array method will modify Array.length; The length of this array is not changed by "delete"; This is different from Array method : 
splice().

//exp 4 :push
a=[0,1,2,3,4];
a[6.5]=6.5;
a.length=2;
a.push("k");

trace(a.length);
trace(a);


Array.push will check Array.length first. Then the elements are pushed as tail at that index. In this example, "k" is pushed to a[2] as tail; Please note that, Array.push can push more than one elements. So, a[2] is changed to "k" and a[3], a[4] are trimed off and deleted. The a[6.5] stay there. Array method can not access or modify something like a[6.5] or a[-1]; They are properties of the object not Array.

//exp 5 pop
a=[0,1,2,3,4];
a.length=3;
trace(a.pop());

trace(a.length);

Array.pop also check Array.length and then retrieve the element at that index. The tail is cut off and deleted.


Ok, that is enough, lets go to some practical discussion:

1. Array for loop and Object for-in loop

It is common that we need to scan the content of Array. 

For example an array a=["red","blue","white"];

we use Array for-loop:

for( i=0;i<a.length;i++){
    trace(a[i]);
}


This can also be done by Object fon-in loop:

for (i in a) {
    trace(a[i]);
}


Please note that, the order of trace in for-in loop is different from Array index loop. In this example, the order is just a reverse one. The "white" get traced out first.

Sometimes we need sequential check and the order is important. If not, for-in loop is more efficient than index looping. We see that, in the index looping, system need to do an addition calculation: "i++" and one comparison with a.length to decide continue or not;

The other usage of Object for-in loop is to scan an Array that contains interrupted elements. For example:
a=[];
a[0]="red";
a[3]="blue";
a[102]="white";

The array length will be 103. If we use index for loop, we need to scan 102 loops for 102 elements while 99 of them are undefined. If we scan it by for-in loop, it is completed by 3 loops.

This is useful in shooting game. We might create our enemies from enemy0 to enemy50 at some time. Among them, maybe 30 enemies had already expired and get removed by removeMovieClip(). We need to check the hitTest between them and bullets. If we use index for loop, it needs 50 loops. Among that 30 loops are waste. I would like to use for-in loop in this condition. 

2. Copy Arrays:

We all know that, array variable just stores the reference of array instance. Create a new variable is not to create another Array. 

Arr1=["red',"blue"];
Arr2=Arr1;
Arr2.push("white");
trace(Arr1);


Any manipulation to Arr2 is to manipulate the array instance. So do Arr1.

Then how do we copy an Array. I mean create another array with the same contents of one array ? The script is:

Arr1=["red","blue"];
Arr2=[];
for(i=0;i<Arr1.length;i++){
    Arr2[i]=Arr1[i];
}


Here are two tricks that copy Array by one line of script.

The first trick is:

Arr1=["red","blue"];
Arr2=Arr1.concat();


That script says: B=A+0; So, B will contains the same elements of A.

The second trick is:

Arr1=["red","blue"];
Arr2=Arr1.slice(0);


The script says: B=A-0; So, B will contains the same elements of A.


Copy Array by assigning __proto__

If you have experience in designing Chess AI, pathFinder, or simple as tic-tac-toe, you probably have the same frustration as me. If we store our data in an Array, we need repeatedly copy a new one to test our move but let the original one no touched. If our AI going to test what will be after 5 moves, then the new Arrays might occupies too much memory and also the copying procedure is a hard work for CPU.

It is simpler and easier to use __proto__ to "copy" an Array. Strictly, it is not a real copy. Anyway, if only we stay in Object method and not usingArray method, it serves our needs well.


a = ["red", "blue", "white"];
b = {};
b.__proto__ = a;
b[1] = "grey";

for (var k = 0; k<b.length; k++) {
    trace(b[k]);
}


2. multi-dimensional array

There is no multi-dimensional Array in Flash. 

Really ? Yes, really. What we see arr[x][y] is strictly not a 2 dimensional array.

In C , we have an Array like this : arr[3,4]; (Please note that, it is not arr[3][4];); In C, arr=new Array[3,4] will create 12 memory allocation for this array, a true 2-dimension with 3 column and 4 rows. If we make arr[1,2]="blue", then we store the value "blue" into that memory piece at column 1- row 2. In C, we can not access it by single index like this : arr[3]="blue" or arr[3]=[a,b,c]; For a 2-dimensional array, we always supply 2 index number to access the value. 


In Action script, we can not say arr=[][]; We can only initialize one dimensional array.

Think about this work around to simulate 2 dimensional array in Flash:

color0=["red","orange","yellow","grey"];
color1=["green","blue","cyan","pink"];
color2=["violet","white","black","aqua"];

mix=[color0,color1,color2];


When we say mix[1][2], we are accessing (mix[1])[2], that is colors1[2]. Here we see 3 memory pieces storing reference of one dimensional array. Each one dimensiona array have 4 pieces of memory. Total 3+(3x4)=15 memory pieces. 

In the above example, we can say "mix[1][100]="magenta"; That is all right, we are saying (mix[1])[100]="magenta", that is to say "color1[100]="magenta"; But, we can not say mix[100][2]="magenta". By that we mean (mix[100])[2]="magenta"; However, there is no (mix[100]). It is undefined not an Array, so we can not access the 2-indexed elements. 

Because it is single dimensional array, so we can easily say: mix[2]=["dark","bright"]; Then mix[2][0] will be "dark"; That is (mix[2])[0];

In C, accessing arr[3,4] is :
"access the memory piece at col 3, row 4";

In ActionScript, accesing arr[3][4] is:
"accessing the 4-indexed elements in the 3-indexed elements of the Array arr";