Looping means repeating a block of code while a condition is true. This is achieved in JavaScript using two statements, the while statement and the for statement. We'll be looking at these shortly, but why would we want to repeat blocks of code anyway?
Well, take the situation where you have a series of results, say average temperatures for each month in a year, and you want to plot these on a graph. The code needed for plotting each point will most likely be the same. So, rather than write out the code 12 times (once for each point), it's much easier to execute the same code 12 times by using the next item of data in the series. This is where the for statement would come in handy, because we know how many times we want the code to execute.
In another situation, you might want to repeat the same piece of code all the while a certain condition is true, for example while the user keeps clicking a Start Again button. In this situation, the while statement would be very useful.
The for statement allows you to repeat a block of code a certain number of times. The syntax is illustrated in Figure 3-10.
Let's look at the makeup of a for statement. We can see from Figure 3-10 that, just like the if and switch statements, the for statement also has its logic inside parentheses. However, this time it's split into three parts, each part separated by a semicolon. For example, in the figure we have the logic
(var loopCounter = 1; loopCounter <= 3; loopCounter++)
The first part of the for statement's logic is the initialization part of the for statement. To keep track of how many times we have looped through the code, we need a variable to keep count. It's in the initialization part that we initialize variables. In the example we have declared loopCounter and set it to the value of 1. This part is only executed once during the execution of the loops, unlike the other parts. We don't need to declare the variable if it was declared earlier in the code.
var loopCounter; for (loopCounter = 1; loopCounter <= 3; loopCounter++)
Following the semicolon, we have the test condition part of the for statement. The code inside the for statement will keep executing for as long as this test condition evaluates to true. After the code is looped through each time, this condition is tested. In Figure 3-10, we execute for as long as loopCounter is less than or equal to three. The number of times a loop is performed is often called the number of iterations.
Finally, we have the increment part of the for loop, where variables in our loop's test condition have their values incremented. Here we can see that loopCounter is incremented by one using the ++ operator we saw in Chapter 2. Again, this part of the for statement is repeated with every loop of the code. Although we call it the increment part, it can actually be used to decrease or decrement the value, for example if we wanted to count down from the top element in an array to the first.
After the for statement, we have the block of code that will be executed repeatedly, as long as the test condition is true. This block of code is contained within curly braces. If the condition is never true, even at the first test of the loop condition, then the code inside the for loop will be skipped over and never be executed.
Putting all this together, how does the for loop work?
Execute initialization part of the for statement.
Check the test condition. If true, continue; if not, exit the for statement.
Execute code in the block after the for statement.
Execute the increment part of the for statement.
Repeat steps 2 through 4 until the test condition is false.
Let's change our temperature converter so that it converts a series of values, stored in an array, from Fahrenheit to centigrade. We will be using the for statement to go through each element of the array. Type in the code and save it as ch3_examp4.htm.
<html> <body> <script language="JavaScript" type="text/javascript"> var degFahren = new Array(212, 32, -459.15); var degCent = new Array(); var loopCounter; for (loopCounter = 0; loopCounter <= 2; loopCounter++) { degCent[loopCounter] = 5/9 * (degFahren[loopCounter] - 32); } for (loopCounter = 2; loopCounter >= 0; loopCounter--) { document.write("Value " + loopCounter + " was " + degFahren[loopCounter] + " degrees Fahrenheit"); document.write(" which is " + degCent[loopCounter] + " degrees centigrade<br>"); } </script> </body> </html>
On loading this into your browser, you'll see a series of three lines in the page containing the results of converting our array of Fahrenheit values into centigrade (as shown in Figure 3-11).
Our first task is to declare the variables we are going to use. First, we declare and initialize degFahren to contain an array of three values, 212, 32, and –459.67. Next, degCent is declared as an empty array. Finally, loopCounter is declared and will be used to keep track of which array index we are accessing during our looping.
var degFahren = new Array(212, 32, -459.67); var degCent = new Array(); var loopCounter;
Following this comes our first for loop.
for (loopCounter = 0; loopCounter <= 2; loopCounter++) { degCent[loopCounter] = 5/9 * (degFahren[loopCounter] - 32); }
In the first line, we start by initializing the loopCounter to zero. Then the for loop's test condition, loopCounter <= 2, is checked. If this condition is true, the loop executes for the first time. Once the code inside the curly braces has executed, the incrementing part of the for loop, loopCounter++, will be executed, and then the test condition will be re-evaluated. If it's still true, another execution of the loop code is performed. This continues until the for loop's test condition evaluates to false, at which point looping will end, and the first statement after the closing curly brace will be executed.
The code inside the curly braces is the equation we saw in earlier examples, only this time we are placing its result into the degCent array, with the index being the value of loopCounter.
In the second for loop we write the results contained in our degCent array to the screen.
for (loopCounter = 2; loopCounter >= 0; loopCounter--) { document.write("Value " + loopCounter + " was " + degFahren[loopCounter] + " degrees Fahrenheit"); document.write(" which is " + degCent[loopCounter] + " degrees centigrade<br>"); }
This time we're counting down from 2 to 0. The variable loopCounter is initialized to 2, and the loop condition remains true until loopCounter is less than zero. This time loopCounter is actually decremented each time rather than incremented, using loopCounter—. Again, loopCounter is serving a dual purpose: it keeps count of how many loops we have done and also provides the index position in the array.
Note |
Note that in these examples, we've used whole numbers in our loops. However, there is no reason why you can't use fractional numbers, although it's much less common to do so. |
This loop works primarily with arrays, and as we'll see in the next chapter, it also works with something called objects. It allows us to loop through each element in the array without having to know how many elements the array actually contains. In plain English, what this loop says is, "For each element in the array, execute some code." Rather than us having to work out the index number of each element, the for...in loop does it for us and automatically moves to the next index with each iteration (loop through).
Its syntax for use with arrays is
for (index in arrayName) { //some code }
In this code extract, index is a variable we declare prior to the loop, which will automatically be populated with the next index value in the array. arrayName is the name of the variable holding the array we want to loop through.
Let's look at an example to make things clearer. We'll define an array and initialize it with three values.
var myArray = new Array("Paul","Paula","Pauline");
To access each element using a conventional for loop, we'd write
var loopCounter; for (loopCounter = 0; loopCounter < 3; loopCounter++) { document.write(myArray[loopCounter]); }
To do exactly the same thing with the for...in loop, we write
var elementIndex; for (elementIndex in myArray) { document.write(myArray[elementIndex]); }
As you can see, the code in the second example is a little clearer, as well as being shorter. Both methods work equally well and will iterate three times. However, if you increase the size of the array, for example by adding the element myArray[3] = "Philip", the first method will still only loop through the first three elements in the array, whereas the second method will loop through all four elements.
Whereas the for loop is used for looping a certain number of times, the while loop allows you to test a condition and keep on looping while it's true. The for loop is useful when you know how many times you need to loop, for example when you are looping through an array that you know has a certain number of elements. The while loop is more useful when you don't know how many times you'll need to loop. For example, if you are looping through an array of temperature values and want to continue looping while the temperature value contained in the array element is less than 100, you will need to use the while statement.
Let's take a look at the structure of the while statement, as illustrated in Figure 3-12.
We can see that the while loop has fewer parts to it than the for loop. The while loop consists of a condition which, if it evaluates to true, causes the block of code inside the curly braces to execute once, and then the condition is re-evaluated. If it's still true, the code is executed again, the condition is re-evaluated again, and so on until the condition evaluates to false.
One thing to watch out for is that if the condition is false to start with, the while loop never executes. For example
degCent = 100; while (degCent != 100) { // some code }
Here, the loop will run if degCent does not equal 100. However, since degCent is 100, the condition is false, and the code never executes.
In practice we would normally expect the loop to execute once; whether it executes again will depend on what the code inside the loop has done to variables involved in the loop condition. For example
degCent = new Array(); degFahren = new Array(34, 123, 212); var loopCounter = 0; while (loopCounter < 3) { degCent[loopCounter] = 5/9 * (degFahren[loopCounter] - 32); loopCounter++; }
The loop will execute so long as loopCounter is less than three. It's the code inside the loop (loopCounter++;) that increments loopCounter and will eventually cause loopCounter < 3 to be false so that the loop stops. Execution will then continue on the first line after the closing brace of the while statement.
Something to watch out for is the infinite loop—a loop that will never end. Suppose we forgot to include the loopCounter++; line in the code. Leaving this line out would mean that loopCounter will remain at zero, so the condition (loopCounter < 3) will always be true, and the loop will continue until the user gets bored, cross, and shuts down her browser. However, it is an easy mistake to make and one JavaScript won't warn you about.
It's not just missing out lines that can cause infinite loops, but also mistakes inside the loop's code. For example
var testVariable = 0; while (testVariable <= 10) { alert("Test Variable is " + testVariable); testVariable++; if (testVariable = 10) { alert("The last loop"); } }
See if you can spot the deliberate mistake that leads to an infinite loop—yes, it's the if statement that will cause this code to go on forever. Instead of using == as the comparison operator in the condition of the if statement, we put =, so testVariable is set to 10 again in each loop, despite the line, testVariable++. This means that at the start of each loop, the test condition always evaluates to true, since 10 is less than or equal to 10. Put the extra = in to make if (testVariable == 10), and everything is fine.
With the while loop, we saw that the code inside the loop only executes if the condition is true; if it's false, the code never executes, and execution instead moves to the first line after the while loop. However, there may be circumstances when you want the code in the while loop to execute at least once, regardless of whether the condition in the while statement evaluates to true. It might even be that code inside the while loop needs to be executed before we can test the while statement's condition. It's situations like this for which the do...while loop is ideal.
Let's look at an example where we want to get the user's age via a prompt box. We want to show the prompt box but also make sure that what the user has entered is a number.
var userAge; do { userAge = prompt("Please enter your age","") } while (isNaN(userAge) == true);
The code line within the loop
userAge = prompt("Please enter your age","")
will be executed regardless of the while statement's condition. This is because the condition is not checked until one loop has been executed. If the condition is true, the code is looped through again. If it's false, then looping stops.
Note that within the while statement's condition, we are using the isNaN() function that we saw in Chapter 2. This checks whether the userAge variable's value is NaN (not a number). If it is not a number, the condition returns a value of true, otherwise it returns false. As we can see from the example, it allows us to test the user input to ensure the right data has been entered. The user might lie about his age, but at least we know he entered a number!
The do...while loop is fairly rare; there's not much you can't do with the while loop that can only be done with a do...while loop, so it's best avoided unless really necessary.
We met the break statement earlier when we looked at the switch statement. Its function inside a switch statement is to stop code execution and move execution to the next line of code after the closing curly brace of the switch statement. However, the break statement can also be used as part of the for and while loops when you want to exit the loop prematurely. For example, suppose you're looping through an array, like we did with the temperature conversion example, and you hit an invalid value. In this situation, you might want to stop the code in its tracks, notify the user that the data is invalid, and leave the loop. This is one situation where the break statement comes in handy.
Let's see how we could change the example where we converted a series of Fahrenheit values (ch3_examp4.htm), so that if we hit a value that's not a number we stop the loop and let the user know about the invalid data.
<script language="JavaScript" type="text/javascript"> var degFahren = new Array(212, "string data", -459.67); var degCent = new Array(); var loopCounter; for (loopCounter = 0; loopCounter <= 2; loopCounter++) { if (isNaN(degFahren[loopCounter])) { alert("Data '" + degFahren[loopCounter] + "' at array index " + loopCounter + " is invalid"); break; } degCent[loopCounter] = 5/9 * (degFahren[loopCounter] - 32); }
We have changed the initialization of the degFahren array so that it now contains some invalid data. Then, inside the for loop, an if statement is added to check whether the data in the degFahren array is not a number. This is done using the isNaN() function; it returns true if the value passed to it in the parentheses, here degFahren[loopCounter], is not a number. If the value is not a number, we tell the user where in the array we have the invalid data. Then we break out of the for loop altogether, using the break statement, and code execution continues on the first line after the end of the for statement.
That's the break statement, but what about continue? The continue statement is similar to break in that it stops the execution of a loop at the point it is found, but instead of leaving the loop, it starts execution at the next iteration, starting with the for or while statement's condition being re-evaluated, just as if the last line of the loop's code had been reached.
In the break example, it was all or nothing—if even one piece of data was invalid, we broke out of the loop. It might be better if we tried to convert all the values in degFahren, but if we hit an invalid item of data in the array, we notify the user and continue with the next item, rather than giving up as our break statement example does.
if (isNaN(degFahren[loopCounter]))
{
alert("Data '" + degFahren[loopCounter] + "' at array index " +
loopCounter + " is invalid");
continue;
}
Just change the break statement to a continue. We will still get a message telling us about the invalid data, but the third value will also be converted.