The purpose of this series of lessons is to teach you how to program in JavaScript. The goal is to provide a programming tutorial that will be accessible to persons with no programming experience and will be equally useful to persons who already have programming experience using JavaScript or some other language.
Although you don't hear too much about it these days, programming instructors used to make a big deal about sequence, selection, and loop. (That was back when there wasn't much else to make a big deal about.) Programming these days involves so many new and more complex abstract concepts that these three have been relegated to the appendix in many books on computer programming.
The concept here is that the statements in a script are executed in sequence until a point is reached where it is necessary to either select a fork in the road, or loop and repeat the execution of a given set of statements more than once.
I recall one Pascal programming book using an analogy something like:
This lesson will be primarily concerned with learning about the flow
of control in JavaScript.
The following table is a partial list of the statements supported by
JavaScript for controlling the logical flow of the script. Some additional
statements will be presented in conjunction with the study of objects.
Statement | Type |
if-else | selection |
switch-case | selection |
for | loop |
while | loop |
do-while | loop |
break | miscellaneous |
continue | miscellaneous |
label | miscellaneous |
return | miscellaneous |
JavaScript supports two conditional statements:
if(conditional expression) statement or compound statement; else //optional statement or compound statement; //optional |
A compound statement is one or more individual statements enclosed in curly braces {} and treated as a group. This is often called a block in some languages.
The following sample script illustrates the behavior of the if-else
statement.
<!-- File Js00000140.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of the if-else statement. The output from running this script is: x is less than y Second statement in compound statement if branch, x is less than y else branch, x is not greater than y Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script x = 5; y = 6; z = 7; <!-- if without an else, compound statement --> if(x<y){ document.write("x is less than y<BR>"); document.write("Second statement in compound statement<BR>"); }//end compound statement for if <!-- if with an else, not a compound statement --> if(x < y) document.write("if branch, x is less than y<BR>") else document.write("else branch, x is not less than y<BR>"); <!-- another if with an else --> if(x > y) document.write("if branch, x is greater than y<BR>"); else document.write("else branch, x is not greater than y<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
The condition can be any JavaScript expression that evaluates to true or false. The statements to be executed can be any JavaScript statements, including further nested if statements. If you want to use more than one statement after an if or else statement, you must enclose the statements in curly braces, {}. |
switch(expression){ case constant: //sequence of optional statements break; //optional case constant: //sequence of optional statements break; //optional . . . default //optional //sequence of optional statements } |
In JavaScript, the constant can be of numeric, string, or boolean type. In the case of boolean, it is similar to an if-else statement.
Because of accuracy considerations, you should probably avoid using numeric values having fractional parts that have been previously calculated for matching purposes. A very small difference in two calculated values could prevent a match.
Execution of statements continues until the optional break is encountered. When break is encountered, execution of the switch statement is terminated and control is passed to the next statement following the switch statement.
If no match is found and the optional default keyword along with a sequence of optional statements has been provided, those statements will be executed.
Switch statements can be nested as illustrated in the follow script. This script also illustrates what can happen if you forget to include the break statement. Note the line of output from this script that states that 8matches 9. This is the result of neglecting to include the break where appropriate and two statements were executed instead of just the one that should have been executed.
Note that it is not necessary to include multiple statements inside
of curly braces {} to cause multiple statements to be executed inside of
a switch statement.
<!-- File Js00000150.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of the unlabeled switch-case statement. The output from running this script is: 5 matches 5 No match found for 3 cat matches cat No match found for pig true matches true false matches false 8matches 8 8matches 9 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script <!-- switch using numeric constants with a match --> x = 5; switch(x){ case 4: document.write(x + " matches 4");break case 5: document.write(x + " matches 5");break case 6: document.write(x + " matches 6");break default: document.write("No match found for " + x); }//end switch statement document.write("<BR>"); <!-- switch using numeric constants without a match --> x = 3; switch(x){ case 4: document.write(x + " matches 4");break case 5: document.write(x + " matches 5");break case 6: document.write(x + " matches 6");break default: document.write("No match found for " + x); }//end switch statement document.write("<BR>"); <!-- switch using string constants with a match --> x = "cat"; switch(x){ case "dog": document.write(x + " matches dog");break case "cat": document.write(x + " matches cat");break case "rat": document.write(x + " matches rat");break default: document.write("No match found for " + x); }//end switch statement document.write("<BR>"); <!-- switch using string constants without a match --> x = "pig"; switch(x){ case "dog": document.write(x + " matches dog");break case "cat": document.write(x + " matches cat");break case "rat": document.write(x + " matches rat");break default: document.write("No match found for " + x); }//end switch statement document.write("<BR>"); <!-- switch using boolean constants --> x = "true"; switch(x){ case "true": document.write(x + " matches true");break case "false": document.write(x + " matches false");break }//end switch statement document.write("<BR>"); <!-- another switch using boolean constants and nesting--> x = "false", y = 8; switch(x){ case "true": document.write(x + " matches true<BR>");//no break here switch(y){ case 8: document.write(y + "matches 8<BR>");//no break case 9: document.write(y + "matches 9<BR>"); }//end nested switch statement case "false": document.write(x + " matches false<BR>");//no break here switch(y){ case 8: document.write(y + "matches 8<BR>");//no break case 9: document.write(y + "matches 9<BR>"); }//end nested switch statement }//end switch statement document.write("<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
A while statement executes its statements as long as a specified condition evaluates to true. It is probably the most straightforward of the three types of loops listed above.
The general syntax of a while statement is as follows
while (conditional expression) statement or compound statement; |
As with all loop statements, you must be careful to make certain that the conditional expression eventually evaluates to false. Otherwise, control will be trapped inside the while statement in what is commonly called an infinite loop.
The while statement is used to form an entry condition loop. The significance of an entry condition loop is that the conditional expression is tested before the statements in the body of the loop are executed. If it tests false initially, the statements in the loop will not be executed.
The following script illustrates the use of a simple while loop. This script initializes the value of a counter to 4 and then loops while the value of the counter is greater than 0.
During each pass through the loop (commonly called an iteration), a
decrement instruction is used to subtract one from the counter. The
value of the counter is tested at the beginning of each iteration.
When the value of the counter reaches zero, control is passed to the next
instruction following the loop. In this case, there aren't any more
instructions, so the script simply terminates
<!-- File Js00000160.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of the while loop statement. The output from running this script is: cnt = 4 cnt = 3 cnt = 2 cnt = 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script cnt = 4;//initialize a counter while(cnt > 0){//begin while loop //display value of counter document.write("cnt = " + cnt + "<BR>"); --cnt;//decrement counter }//end while loop // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
This script uses a counter named oCnt to control the outer loop and a counter named iCnt to control the inner loop. oCnt is initialized to a value of 4, and the outer loop is designed to loop for as long as the value of this counter remains greater than zero. The value of the counter is decremented by one at the end of each iteration of the outer loop.
The counter for the inner loop named iCnt is initialized to a value of 5 inside the outer loop. Then an inner loop is executed that continues to loop for as long as the value of this counter remains greater than zero. The counter for the inner loop is decremented by one at the end of each iteration of the inner loop.
Perhaps the most important thing to notice is that for every iteration of the outer loop, the inner loop iterates through its full range of iterations.
As you can see, the output from this script forms a sort of a rectangular
array with the value of oCnt indicating the row number and the value
of iCnt indicating a column number. In fact, nested while
loops of this sort are often used to process two-dimensional arrays (arrays
will be covered in a subsequent lesson).
<!-- File Js00000170.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of nested while loops. The output from running this script is: oCnt = 4 -- iCnt = 5 iCnt = 4 iCnt = 3 iCnt = 2 iCnt = 1 oCnt = 3 -- iCnt = 5 iCnt = 4 iCnt = 3 iCnt = 2 iCnt = 1 oCnt = 2 -- iCnt = 5 iCnt = 4 iCnt = 3 iCnt = 2 iCnt = 1 oCnt = 1 -- iCnt = 5 iCnt = 4 iCnt = 3 iCnt = 2 iCnt = 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script oCnt = 4;//initialize a counter while(oCnt > 0){//begin outer loop //display value of oCnt document.write("<BR>oCnt = " + oCnt + " -- "); iCnt = 5;//initialize another counter while(iCnt > 0){//begin inner loop document.write("iCnt = " + iCnt + " "); iCnt--;//decrement iCnt }//end inner loop --oCnt;//decrement counter }//end outer loop // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
do { statements } while (conditional expression); |
All loop structures in JavaScript can be nested inside of other statements, including other loop structures of the same or a different type.
The following script illustrates the use of a simple do-while loop structure. This script is designed to illustrate the special quality of this structure that causes the statements inside the body of the loop to be executed once even if the conditional test fails the first time.
The script contains two identical do-while structures. The only difference between the two is the initial value of a counter that is used in the conditional test. Each structure iterates for as long as the value of the counter remains greater than zero.
In the second structure, the value of the counter is initially zero.
Therefore, the test fails the first time it is made and the loop terminates
the first time the test is made. Because the statements inside the
loop occur before the test is made, those statements are executed once.
<!-- File Js00000180.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of the do-while loop statement. The output from running this script is: cnt = 4 cnt = 3 cnt = 2 cnt = 1 Force false condition initially cnt = 0 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script cnt = 4;//initialize a counter do{//begin do-while loop //display value of counter document.write("cnt = " + cnt + "<BR>"); --cnt;//decrement counter }while(cnt > 0)//end while loop document.write("<BR>Force false condition initially<BR>"); cnt = 0;//initialize a counter do{//begin do-while loop //display value of counter document.write("cnt = " + cnt + "<BR>"); --cnt;//decrement counter }while(cnt > 0)//end while loop // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
A for loop iterates until a specified condition evaluates to
false. The heart of a for loop consists of three clauses separated
by semicolons as shown below.
for (first clause; second clause; third clause) simple or compound statement |
In other languages, the comma operator guarantees that its left operand will be executed before its right operand, and presumably this is also true in JavaScript, although I haven't been able to find that stated anywhere.
The expressions in the first clause are executed only once, at the beginning of the loop. Any legal expression(s) may be contained in the first clause, but typically the first clause is used for initialization.
Note that variables can also be declared and initialized in the first clause. (For those of you who have programmed in Java or C++, note that declaring variables in the first clause in JavaScript doesn't restrict the scope of those variables as it does in Java and C++.)
The second clause consists of a single expression which must eventually evaluate to false to cause the loop to terminate.
Typically relational expressions or relational and logical expressions are used in the second clause.
The value of the second clause is tested when the statement first
begins execution, and at the beginning of each iteration thereafter.
Therefore, the for loop is an entry condition loop.
Contrary to some current (May 98) Netscape documentation, although the third clause appears physically at the top of the loop, it isn't executed until the statements in the body of the loop have completed execution. This is demonstrated in the sample program that follows. |
Multiple expressions can appear in the third clause, separated by the comma operator. If variables are updated in the third clause and used in the body of the loop, it is important to understand that they do not get updated until the execution of the body is completed.
The following script illustrates the use of a for loop. This script declares and initializes two variables named x and y in the first clause of the for loop. The variable named x is the control variable for the loop, and the loop continues to iterate for as long as the value of x is greater than zero. The variable y is used simply to illustrate the update behavior of the loop.
Both variables are updated in the third clause of the loop by decrementing them by one. Both variables are displayed in the body of the loop.
An important point to note is that the two variables are initialized to values of 3 and 4 and they still have that value the first time their values are displayed in the body of the loop, even though they are decremented in the third clause. This demonstrates that even though the update code is physically written at the top of the loop structure, the actual update isn't executed until the code in the body of the loop has been executed.
Again, for the benefit of Java and C++ programmers, the values of the
two variables are also displayed after the loop has terminated which is
different behavior than in Java and C++.
<!-- File Js00000190.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of a for loop. The output from running this script is: Inside loop: x, y = 3, 4 Inside loop: x, y = 2, 3 Inside loop: x, y = 1, 2 Outside loop: x, y = 0, 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script for(x=3,y=4; x > 0; x--,y--){ document.write("Inside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); }//end for loop document.write("Outside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
The update of the two variables is embedded in the body of the loop
(at the end) and the third clause is also left blank. The output
is identical to that of the previous script, further reinforcing my earlier
claims as to when the statements in the update clause of a for loop
are executed.
<!-- File Js00000200.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate the use of a for loop with empty first and third clauses. The output from running this script is: Inside loop: x, y = 3, 4 Inside loop: x, y = 2, 3 Inside loop: x, y = 1, 2 Outside loop: x, y = 0, 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script x=3, y=4; for( ; x > 0; ){ document.write("Inside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); x--; y--; }//end for loop document.write("Outside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
Another area where semicolons are required is in the writing of event
handlers, a topic that will be covered in a subsequent lesson. In
that case, you sometimes don't have any choice but to put two or more statements
on the same line which in turn requires the use of semicolons.
<!-- File Js00000210.htm Copyright 1998, R.G.Baldwin This JavaScript script is designed to illustrate that the semicolon is required in JavaScript only to separate two statements on the same line and as separators in a for loop. The output from running this script is: Inside loop: x, y = 3, 4 Inside loop: x, y = 2, 3 Inside loop: x, y = 1, 2 Outside loop: x, y = 0, 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script x=3, y=4 for( ;x > 0; ){ document.write("Inside loop: ") document.write("x, y = " + x + ", " + y + "<BR>") x--; y--//note the semicolon separator }//end for loop document.write("Outside loop: ") document.write("x, y = " + x + ", " + y + "<BR>") // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
In my opinion, because there is a good possibility that you might like to also learn to program using Java someday, you should become accustomed to the placement of a semicolon to terminate each statement by using that programming style in JavaScript. It is easier to form good habits in the beginning than to break bad habits later on. Therefore, unless I forget to do so, you will see semicolons to terminate all of the statements in my JavaScript scripts.
The previous discussions on loops stated that the various loops continue to iterate for as long as some particular condition is true. That was only half the truth. In fact, it is possible to modify that behavior by making use of break and continue.
In a nutshell, break can be used to cause a loop to terminate prematurely. continue can be used to cause a particular iteration of a loop to terminate prematurely so that the next iteration begins immediately.
In addition, both break and continue can be used with
a label to provide even more complex behavior. This capability
mimics a capability that is also available in Java. I am a very experienced
Java programmer and I rarely find the need to use labeled break
and continue statements. Therefore, I will discuss the unlabeled
versions first followed by a brief discussion of the labeled versions.
When break is encountered in a loop, it causes control to be passed to the next statement outside the innermost enclosing loop. Loops can also be nested inside other loops and an unlabeled break statement only impacts the loop statement in which it appears.
The continue statement cannot be used in a switch statement. It is confined to loops.
When an unlabeled continue statement is encountered in a loop, it causes the current iteration to be terminated and the next iteration to begin.
The following sample script illustrates the use of an unlabeled break in a for loop. You might note that this is a modification of a script that was discussed earlier.
In this version, an if statement was inserted in the body of
the loop that causes the loop to break when the value of the variable
named y is equal to 3. As a result, even though the loop is
designed to iterate until the value of the control variable x reaches
zero (as in the sample script discussed earlier), the countdown terminates
early because of the break. When x is displayed after
the loop terminates, it has a value of 1 so it was never allowed to reach
zero as in the previous sample script.
<!-- File Js00000220.htm Copyright 1998, R.G.Baldwin This script is designed to illustrate the use of an unlabeled break in a for loop. The output from running this script is: Inside loop: x, y = 4, 5 Inside loop: x, y = 3, 4 Inside loop: x, y = 2, 3 Outside loop: x, y = 1, 2 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script for(x=4,y=5; x > 0; x--,y--){ if(y==3) break; document.write("Inside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); }//end for loop document.write("Outside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
Inside loop: x, y = 2, 3
This is because the continue statement caused the iteration that
would have produced that output to be terminated prematurely and the next
iteration to begin immediately following the continue. As
a result, the document.write(...) statement in the body of the loop
wasn't executed during that iteration and this line of output wasn't produced.
<!-- File Js00000230.htm Copyright 1998, R.G.Baldwin This script is designed to illustrate the use of an unlabeled continue in a for loop. The output from running this script is: Inside loop: x, y = 4, 5 Inside loop: x, y = 3, 4 Inside loop: x, y = 1, 2 Outside loop: x, y = 0, 1 Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script for(x=4,y=5; x > 0; x--,y--){ if(y==3) continue; document.write("Inside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); }//end for loop document.write("Outside loop: "); document.write("x, y = " + x + ", " + y + "<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
The general syntax of a labeled statement is as follows:
label : statement |
Basically, a label can be used with break to cause control to break out of any labeled compound statement as illustrated in the following sample script.
This script contains two labeled compound statements that are essentially identical. However, a test is performed inside of each, and if the result if the test is true, a labeled break is executed on that compound statement.
The demonstration is designed to cause the test to be true in the first
compound statement and false in the second compound statement. As
a result, when control breaks out of the first compound statement, the
document.write() statement is skipped as indicated one line of missing
output in the comments at the beginning of the script.
<!-- File Js00000240.htm Copyright 1998, R.G.Baldwin This script is designed to illustrate the use of a labeled break in a compound statement. The output from running this script is: Enter first compound statement Out of first compound statement Enter second compound statement Still in second compound statement Out of second compound statement Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script document.write("Enter first compound statement<BR>"); aLabel:{//begin compound statement myVar = 5; if(myVar == 5)break aLabel; document.write("Still in first compound statement<BR>"); }//end compound statement document.write("Out of first compound statement<BR>"); document.write("<BR>Enter second compound statement<BR>"); bLabel:{//begin compound statement myVar = 6; if(myVar == 5)break bLabel; document.write("Still in second compound statement<BR>"); }//end compound statement document.write("Out of second compound statement<BR>"); // End hiding --> </SCRIPT> </HEAD> <BODY> <P> Done. </BODY> </HTML> |
return may appear any number of times in a function, either with, or without an expression following it. If return is followed by an expression, that expression will be evaluated and the resulting value will be returned to the calling code. If return is not followed by an expression, nothing useful will be returned.
The first time that return is encountered in a function, control is transferred back to the code that invoked the function in the first place. This is illustrated in the following sample script.
This script contains a function named myFunction() that contains a return statement to prematurely terminate the function if the value of the incoming parameter is 5. When the function is not prematurely terminated, an output statement displays the text "Still in myFunction". However, when the return statement is executed to prematurely terminate the function, this output statement is not executed and the text does not appear in the output.
It is also worth noting that a return statement is not required
to terminate a function. If the function simply runs out of statements
to execute, it will terminate naturally and return control to the code
from which it was invoked.
<!-- File Js00000250.htm Copyright 1998, R.G.Baldwin This script is designed to illustrate the use of return to terminate a function prematurely. The output from running this script is: Call myFunction with parameter value of 6 Enter myFunction Still in myFunction Back from myFunction Call myFunction with parameter value of 5 Enter myFunction Back from myFunction Done. --------------------------------------------------------------------> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script function myFunction(data){ document.write("Enter myFunction<BR>"); if(data == 5) return; document.write("Still in myFunction<BR>"); }//end myFunction() // End hiding --> </SCRIPT> </HEAD> <BODY> <SCRIPT LANGUAGE="JavaScript1.2"> <!-- Hide script document.write("Call myFunction with parameter value of 6<BR>"); myFunction(6); document.write("Back from myFunction<BR><BR>"); document.write("Call myFunction with parameter value of 5<BR>"); myFunction(5); document.write("Back from myFunction"); // End hiding --> </SCRIPT> <P> Done. </BODY> </HTML> |