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);