The for-each and for-in loops in JavaScript and AS3 are very convenient ways to avoid the repetition of C-style for loops. Let’s take a look at them all, what they’re good for and bad for, and see if we can find any gotchas.

Here are the three loops:

var a:Array = [new Point(1,2), new Point(3,4), new Point(5,6)];
 
// C-style loop:
for (var i:int = 0; i < a.length; ++i)
{
	trace("The index is: " + i);
}
 
// For-each loop:
for each (var p:Point in a)
{
	trace("The current element is: " + p);
}
 
// For-in loop:
for (var k:* in a)
{
	trace("The index is: " + k);
}

Only the C-style loop could manipulate the iteration during the loop to allow for going backwards, repeating elements, skipping elements, and so forth. You get maximum control at the cost of a lot of typing. You also give up some type safety. When you index the array by the current index, you could get anything back. If the array contains different types, this is really handy. Most arrays don’t do this, so you often end up simply having to deal with an untyped return value. Dealing with untyped values is slow, type-unsafe, and inconvenient as it usually breaks code completion (except with vectors).

The for-each loop is great for arrays containing a single type that simply need to be iterated in the normal front-to-back fashion with no exceptions. This is the vast majority of loops. The for-each loop requires little typing and is type-safe as the iterator is the current element of the array and can therefore be declared with the correct type. The biggest downside is that you don’t get the current element’s index.

The for-in loop is something of a middle ground. You don’t have to type much, but you don’t get type safety or C-style flexibility. It would be great with arrays and vectors if the compiler would allow you to type the iterator as an int, but instead you get a compiler error; the compiler will only allow you to type it as an Object, *, or a String. As such, I consider this a “fast and loose” loop when used with arrays or vectors. It is, however, the only way to go when iterating over objects and dictionaries. When you iterate with a for-in loop over an Object, your iterator is a String and you can type it as such. When iterating over a Dictionary, your iterator is a * since the keys may be any type.

Obviously the Flash Player (or JavaScript engine) is doing some of the C-style loop work behind the scenes. In some cases it isn’t clear just how this is going to work. Consider these simple loops:

function foo(): Array
{
	return [new Point(1,2), new Point(3,4), new Point(5,6)];
}
 
for each (var p:Point in foo())
{
	trace("The current element is: " + p);
}
for (var k:* in foo())
{
	trace("The index is: " + k);
}

The programmer is requesting a loop over the return value of a function call. But is the function called every iteration of the loop? Surely this would be disasterous for performance if the function is allocating a fresh array every time, doing anything complicated, or there are simply a lot of elements to iterate over. Thankfully the result of the function call is cached and the loops end up behaving like this:

var a:Array = foo();
for each (var p:Point in a)
{
	trace("The current element is: " + p);
}
for (var k:* in a)
{
	trace("The index is: " + k);
}

As a final note, all of the above is exactly the same in JavaScript, except of course the parts about vectors and dictionaries.