start page | rating of books | rating of authors | reviews | copyrights

Book HomeActionScript: The Definitive GuideSearch this book

Chapter 8. Loop Statements

Contents:

The while Loop
Loop Terminology
The do-while Loop
The for Loop
The for-in Loop
Stopping a Loop Prematurely
Timeline and Clip Event Loops
Onward!

In the previous chapter, we learned that a conditional causes a statement block to be executed once if the value of its test expression is true. A loop, on the other hand, causes a statement block to be executed repeatedly, for as long as its test expression remains true.

Loops come in a variety of tasty flavors: while, do-while, for, and for-in. The first three types have very similar effects, but with varying syntax. The last type of loop, for-in, is a specialized kind of loop used with objects. We'll start our exploration of loops with the while statement, the easiest kind of loop to understand.

8.1. The while Loop

Structurally, a while statement is constructed much like an if statement: a main statement encloses a block of substatements that are executed only when a given condition is true:

while (condition) {
  substatements
}

If the condition is true, substatements are executed. But unlike the if statement, when the last substatement is finished, execution begins anew at the beginning of the while statement (that is the interpreter "loops" back to the beginning of the while statement). The second pass through the while statement works just like the first: the condition is evaluated, and if it is still true, substatements are executed again. This process continues until condition becomes false, at which point execution continues with any statements that follow the while statement in the script.

Here's an example of a very simple loop:

var i = 3;
while (i < 5) {
  trace("x is less than 5");
}

The example reliably represents the correct syntax of a while loop but is most likely in error. To see why, let's follow along with the interpreter as it executes the example.

We start with the statement before the while statement, var i = 3, which sets the variable i to 3. Because the variable i is used in the test expression of the loop, this step is often called the loop initialization. Next, we begin executing the while statement by resolving the test expression: i < 5. Because i is 3, and 3 is less than 5, the value of the test expression is true so we execute the trace( ) statement in the loop.

With that done, it's time to restart the loop. Once again, we check the value of the test expression. The value of the variable i has not changed, so the test expression is still true and we execute the trace( ) statement again. At this point, we're done executing the loop body, so it's time to restart the loop. Guess what? The variable i still has not changed, so the test expression is still true and we must execute the trace( ) statement again, and again, and again, forever. Because the test expression always returns true, there's no way to exit the loop -- we're trapped forever in an infinite loop, unable to execute any other statements that may come after the while statement. In ActionScript, an infinite loop causes an error, as we'll see later.

Our loop is infinite because it lacks an update statement that changes the value of the variable used in the test expression. An update statement typically causes the test expression to eventually yield false, which terminates the loop. Let's fix our infinite loop by adding an update statement:

var i = 3;
while (i < 5) {
  trace("x is less than 5");
  i++;
}

The update statement, i++, comes at the end of the loop body. When the interpreter goes through our loop, it executes the trace( ) statement as before, but it also executes the statement i++, which adds one to the variable i. With each iteration of the loop, the value of i increases. After the second iteration, i's value is 5, so the test expression, i < 5, becomes false. The loop, therefore, safely ends.

Our loop's update statement performs a fundamental loop activity: it counts. The variable i (called a counter) runs through a predictable numeric sequence -- perfect for methodical tasks such as duplicating movie clips or accessing the elements of an array. Here we duplicate the square movie clip five times without using a loop:

// Name each new clip sequentially and place it on its own level
duplicateMovieClip("square", "square1", 1);
duplicateMovieClip("square", "square2", 2);
duplicateMovieClip("square", "square3", 3);
duplicateMovieClip("square", "square4", 4);
duplicateMovieClip("square", "square5", 5);

And here we do it with a loop:

var i = 1;
while (i <= 5) {
  duplicateMovieClip("square", "square" + i, i);
  i++;
}

Imagine the difference if we were duplicating square 100 times!

Loops are marvelously useful for manipulating data, particularly data stored in arrays. Example 8-1 shows a loop that displays all the elements of an array to the Output window. Note that the first element is number 0, not number 1.

Example 8-1. Displaying an Array with a while Loop

var people = ["John", "Joyce", "Margaret", "Michael"];  // Create an array
var i = 0;
while (i < people.length) {
  trace("people element " + i + " is " + people[i]);
  i++;
}

The result in the Output window is:

people element 0 is John
people element 1 is Joyce
people element 2 is Margaret
people element 3 is Michael

Notice that the variable i is used both in the test expression and as the array index number, as is typical. Here we use i again as an argument for the charAt( ) function:

var city = "Toronto";
trace("The letters in the variable 'city' are ");
var i = 0;
while (i < city.length) {
  trace(city.charAt(i));
  i++;
}

The Output window shows:

The letters in the variable 'city' are:
T
o
r
o
n
t
o

Finally, instead of dissecting data, we use a loop to construct a sentence from a series of words stored in an array:

var words = ["Toronto", "is", "not", "the", "capital", "of", "Canada"];
var sentence;
var i = 0;
while (i < words.length) {
  sentence += words[i];       // Add the current word to the sentence.

  // If it's not the last word...
  if (i < words.length - 1) {
    sentence += " ";          // ...tack on a space.
  } else {
    sentence += ".";          // ...otherwise, end with a period.
  }
  i++;
}
trace(sentence);              // Displays: "Toronto is not the capital of Canada."

Nearly all loops involve some kind of counter (also sometimes called an iterator or index variable). Counters let us cycle sequentially through data. This is particularly convenient when we determine the counter's maximum limit using the length property of the array or string we want to manipulate, as we did in the preceding example.

It's also possible to create a loop whose end point doesn't depend on a counter. As long as the test expression of the loop eventually becomes false, the loop will end. Here, for example, we examine the level stack of the Flash Player to determine the first vacant level:

var i = 0;
while (typeof eval("_level" + i) == "movieclip") {
  i++;
}
trace("The first vacant level is " + i);

// Now load a movie into the vacant level, knowing it's free
loadMovie("myMovie.swf", i);


Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.