Recipe 1.5 Repeating an Operation Many Times

1.5.1 Problem

You want to perform a task multiple times within a single frame.

1.5.2 Solution

Use a loop to perform the same task multiple times within a single frame. For example, you can use a for statement:

for (var i = 0; i < 10; i++) {
  // Display the value of i.

1.5.3 Discussion

When you want to execute the same action (or slight variations thereof) multiple times within a single frame, use a looping statement to make your code more succinct, easier to read, and easier to update. You can use a while statement or a for statement for this purpose, but generally a for statement is the better choice. Both statements achieve the same result, but the for statement is more compact and more familiar to most programmers.

The syntax of a for statement consists of five basic parts:

The for keyword

Every for statement must begin with a for keyword.

Initialization expression

The loop typically employs an index variable (a.k.a. a loop counter) that is initialized when the statement is first encountered. The initialization is performed only once regardless of how many times the loop is repeated.

Test expression

A loop should include a test expression that returns true or false. The test expression is evaluated once each time through the loop. Generally, the test expression compares the index variable to another value, such as a maximum number of loop iterations. The overall expression must evaluate to true for the for statement's body to execute (contrast this with a do . . . while loop, which executes at least once, even if the test expression is false). On the other hand, if the test expression never becomes false, you'll create an infinite loop, resulting in a warning that the Flash Player is running slowly (which appears after 15 seconds).

Update expression

The update expression usually updates the value of the variable used in the test expression so that, at some point, the test expression becomes false and the loop ends. The update expression is executed once each time through the loop. An infinite loop is often caused by failing to update the appropriate variable in the update expression (usually the same variable used in the test expression).

Statement body

The statement body is a block of substatements enclosed in curly braces that is executed each time through the loop. If the test expression is never true, the for statement's body won't be executed.

The for keyword should come first, and it should be followed by the initialization, test, and update expressions enclosed in parentheses. Semicolons must separate the three expressions from one another (although the initialization, test, and update statements are optional, the semicolons are mandatory). The remainder of the for loop is composed of the statement body enclosed in curly braces. The general form is:

for (initialization; test; update) {
  statement body

Here is an example of a for statement that outputs the numbers 0 to 999. Because the index variable i is a local variable, we preface it with the var keyword in the initialization expression.

for (var i = 0; i < 1000; i++) {
trace ("That's the end.");

To understand the for statement, you can follow along with the ActionScript interpreter as it processes the command. In the preceding example, the for keyword tells the interpreter to perform the statements within the for loop as long as the conditional expression is true. The initialization expression is executed only once, and it sets the variable i to 0. Next, the interpreter checks the test expression (i < 1000). Because i is 0, which is less than 1000, the expression evaluates to true and the trace( ) action within the for statement body is executed. The ActionScript interpreter then executes the update statement, in this case i++, which increments i by 1. The interpreter then repeats the process from the top of the loop (but skips the initialization step). So the interpreter again checks whether the test expression is true and, if so, executes the statement body again. It then executes the update statement again. This process repeats until the test expression is no longer true. The last value displayed in the Output window is 999, because once i is incremented to 1000, the test expression no longer evaluates to true and the loop comes to an end. Once the loop terminates, execution continues with whatever commands follow the loop.

Both the initialization and update expressions can include multiple actions separated by commas. The following example simultaneously increments i and decrements j, and displays their values in the Output window:

for (var i = 0, j = 10; i < 10; i++, j--) {
  trace("i is " + i);
  trace("j is " + j);

The preceding example is not the same as using two nested for statements (which is shown in the next code block).

It is also common to use nested for statements. When you use a nested for statement, use a different index variable than that used in the outermost for loop. By convention, the outermost for loop uses the variable i, and the nested for loop uses the variable j. For example:

for (var i = 1; i <= 3; i++) {
  for (var j = 1; j <= 2; j++) {
    trace(i + " X " + j + " = " + (i * j));

The preceding example displays the following multiplication table in the Output window:

1 X 1 = 1
1 X 2 = 2
2 X 1 = 2
2 X 2 = 4
3 X 1 = 3
3 X 2 = 6

It is possible to nest multiple levels of for statements. By convention, each additional level of nesting uses the next alphabetical character as the index variable. Therefore, the third level of nested for statements typically uses k as the index variable:

for (var i = 1; i <= 3; i++) {
  for (var j = 1; j <= 3; j++) {
    for (var k = 1; k <= 3; k++) {
      trace(i + " X " + j + " X " + k + " = " + (i * j * k));

Additionally, you can use for statements to loop backward:

// Count backward from 10 to 1.
for (var i = 10; i > 0; i--) {

You should not use a for statement to perform tasks over time.

Many programmers make the mistake of trying to use for statements to animate movie clips. For example:

for (var i = 0; i < 20; i++) {
  myMovieClip._x += 10;

Although the preceding code moves the movie clip 200 pixels to the right of its starting point, all the updates take place within the same frame. There are two problems with this. First of all, the Stage updates only once per frame, so only the last update is shown on the Stage (causing the movie clip to jump 200 pixels suddenly rather than moving smoothly in 20 steps). And second, even if the Stage updates more often, each iteration through the for loop takes only a few milliseconds, so the animation would happen too quickly. For actions that you want to take place over time, use an onEnterFrame( ) handler (see Recipe 1.6) or set an interval using the setInterval( ) function (see Recipe 1.7).

Moreover, tight repeating loops should not be used to perform lengthy processes (anything that takes more than a fraction of a second). The Flash Player displays a warning whenever a single loop executes for more than 15 seconds. Using an onEnterFrame( ) handler or the setInterval( ) function avoids the warning message and allows Flash to perform other actions in addition to the repeated actions that are part of the loop.

1.5.4 See Also

The for statement is used in many practical situations, and you can see examples in a great many of the recipes throughout this book. See Recipe 6.2 and Recipe 9.10 for some practical examples, and Recipe 2.3, in which the break command is used to exit the loop prematurely. Recipe 6.13 discusses for . . . in loops, which are used to enumerate the properties of an object or array.

    Part I: Local Recipes
    Part II: Remote Recipes