Not everything that can be counted counts, and not every thing that counts can be counted.
—Albert Einstein
Who can control his fate?
—William Shakespeare
The used key is always bright.
—Benjamin Franklin
Intelligence … is the faculty of making artificial objects, especially tools to make tools.
—Henri Bergson
Every advantage in the past is judged in the light of the final issue.
—Demosthenes
Chapter 5 began our introduction to control statements. In this chapter, we introduce JavaScript’s remaining control statements (with the exception of for…in
, which is presented in Chapter 8). In later chapters, you’ll see that control structures are helpful in manipulating objects.
Counter-controlled repetition requires:
1. The name of a control variable (or loop counter).
2. The initial value of the control variable.
3. The increment (or decrement) by which the control variable is modified each time through the loop (also known as each iteration of the loop).
4. The condition that tests for the final value of the control variable to determine whether looping should continue.
To see the four elements of counter-controlled repetition, consider the simple script shown in Fig. 6.1, which displays lines of XHTML text that illustrate the seven different font sizes supported by XHTML. The declaration in line 12 names the control variable (counter
), reserves space for it in memory and sets it to an initial value of 1
. The declaration and initialization of counter
could also have been accomplished by the following declaration and assignment statement:
var counter; // declare counter
counter = 1; // initialize counter to 1
Lines 16–18 in the while
statement write a paragraph element consisting of the string "XHTML font size"
concatenated with the control variable counter
’s value, which represents the font size. An inline CSS style
attribute sets the font-size
property to the value of counter
concatenated to ex
. Note the use of the escape sequence "
, which is placed around attribute style
’s value. Because the double-quote character delimits the beginning and end of a string literal in JavaScript, it cannot be used in the contents of the string unless it is preceded by a to create the escape sequence
"
. For example, if counter
is 5, the preceding statement produces the markup
<p style = "font-size: 5ex" > XHTML font size 5ex </p>
XHTML allows either single quotes ('
) or double quotes ("
) to be placed around the value specified for an attribute. JavaScript allows single quotes to be placed in a string literal. Thus, we could have placed single quotes around the font-size
property to produce equivalent XHTML output without the use of escape sequences.
Placing a double-quote (“) character inside a string literal that is delimited by double quotes causes a runtime error when the script is interpreted. To be displayed as part of a string literal, a double-quote (“) character must be preceded by a to form the escape sequence ”.
Line 19 in the while
statement increments the control variable by 1 for each iteration of the loop (i.e., each time the body of the loop is performed). The loop-continuation condition (line 14) in the while
statement tests whether the value of the control variable is less than or equal to 7
(the final value for which the condition is true
). Note that the body of this while
statement executes even when the control variable is 7
. The loop terminates when the control variable exceeds 7
(i.e., counter
becomes 8
).
The for repetition statement handles all the details of counter-controlled repetition. Figure 6.2 illustrates the power of the for
statement by reimplementing the script of Fig. 6.1.
When the for
statement begins executing (line 15), the control variable counter
is declared and is initialized to 1
(i.e., the first statement of the for
statement declares the control variable’s name and provides the control variable’s initial value). Next, the loop-continuation condition, counter <= 7
, is checked. The condition contains the final value (7
) of the control variable. The initial value of counter
is 1
. Therefore, the condition is satisfied (i.e., true
), so the body statement (lines 16–18) writes a paragraph element in the XHTML document. Then, variable counter
is incremented in the expression ++counter
and the loop continues execution with the loop-continuation test. The control variable is now equal to 2
, so the final value is not exceeded and the program performs the body statement again (i.e., performs the next iteration of the loop). This process continues until the control variable counter
becomes 8
, at which point the loop-continuation test fails and the repetition terminates.
The program continues by performing the first statement after the for
statement. (In this case, the script terminates, because the interpreter reaches the end of the script.)
Figure 6.3 takes a closer look at the for
statement at line 15 of Fig. 6.2. The for
statement’s first line (including the keyword for
and everything in parentheses after for
) is often called the for statement header. Note that the for
statement “does it all”—it specifies each of the items needed for counter-controlled repetition with a control variable.
Note that Fig. 6.3 uses the loop-continuation condition counter <= 7
. If you incorrectly write counter < 7
, the loop will execute only six times. This is an example of the common logic error called an off-by-one error.
Using an incorrect relational operator or an incorrect final value of a loop counter in the condition of a while, for or do…while statement can cause an off-by-one error or an infinite loop.
Using the final value in the condition of a while or for statement and using the <= relational operator will help avoid off-by-one errors. For a loop used to print the values 1 to 10, for example, the initial value of counter should be 1, and the loop-continuation condition should be counter <= 10 rather than counter < 10 (which is an off-by-one error) or counter < 11 (which is correct). Many programmers, however, prefer so-called zero-based counting, in which, to count 10 times through the loop, counter would be initialized to zero and the loop-continuation test would be counter < 10.
The general format of the for
statement is
for ( initialization; loopContinuationTest; increment )
statements
where the initialization expression names the loop’s control variable and provides its initial value, loopContinuationTest is the expression that tests the loop-continuation condition (containing the final value of the control variable for which the condition is true), and increment is an expression that increments the control variable. The for
statement can be represented by an equivalent while
statement, with initialization, loopContinuationTest and increment placed as follows (Section 6.7 discusses an exception to this rule):
initialization;
while ( loopContinuationTest )
{
statements
increment;
}
If the initialization expression in the for
statement’s header is the first definition of the control variable, the control variable can still be used after the for
statement in the script. The part of a script in which a variable name can be used is known as the variable’s scope. Scope is discussed in detail in Chapter 7, JavaScript: Functions.
Place only expressions involving the control variable in the initialization and increment sections of a for statement. Manipulations of other variables should appear either before the loop (if they execute only once, like initialization statements) or in the loop body (if they execute once per iteration of the loop, like incrementing or decrementing statements).
The three expressions in the for
statement are optional. If loopContinuationTest is omitted, JavaScript assumes that the loop-continuation condition is true
, thus creating an infinite loop. One might omit the initialization expression if the control variable is initialized before the loop. One might omit the increment expression if the increment is calculated by statements in the body of the for
statement or if no increment is needed. The increment expression in the for
statement acts like a stand-alone statement at the end of the body of the for
statement. Therefore, the expressions
counter = counter + 1
counter += 1
++counter
counter++
are all equivalent in the incrementing portion of the for
statement. Many programmers prefer the form counter++
. This is because the incrementing of the control variable occurs after the body of the loop is executed, and therefore the postincrementing form seems more natural. Preincrementing and postincrementing both have the same effect in our example, because the variable being incremented does not appear in a larger expression. The two semicolons in the for
statement header are required.
Using commas instead of the two required semicolons in the header of a for statement is a syntax error.
Placing a semicolon immediately to the right of the right parenthesis of the header of a for statement makes the body of that for statement an empty statement. This code is normally a logic error.
The “increment” may be negative, in which case the loop counts downward. If the loop-continuation condition initially is false
, the for
statement’s body is not performed. Instead, execution proceeds with the statement following the for
statement.
The control variable frequently is printed or used in calculations in the body of a for
statement, but it does not have to be. Other times, the control variable is used for controlling repetition but never mentioned in the body of the for
statement.
Although the value of the control variable can be changed in the body of a for statement, avoid changing it, because doing so can lead to subtle errors.
The for
statement is flowcharted much like the while
statement. For example, Fig. 6.4 shows the flowchart of the for
statement
for ( var counter = 1; counter <= 7; ++counter )
document.writeln( "<p style = "font-size: " +
counter + "ex">XHTML font size " + counter +
"ex</p>" );
This flowchart makes it clear that the initialization occurs only once and that incrementing occurs after each execution of the body statement. Note that, besides small circles and arrows, the flowchart contains only rectangle symbols and a diamond symbol.
The examples in this section show methods of varying the control variable in a for
statement. In each case, we write the appropriate for
header. Note the change in the relational operator for loops that decrement the control variable.
a) Vary the control variable from 1
to 100
in increments of 1
.
for (var i =1; i <=100; ++i )
b) Vary the control variable from 100
to 1
in increments of -1
(i.e., decrements of 1
).
for (var i =100; i >=1; --i )
c) Vary the control variable from 7
to 77
in steps of 7
.
for (var i =7; i <=77; i +=7 )
d) Vary the control variable from 20
to 2
in steps of -2
.
for (var i =20; i >=2; i -=2 )
e) Vary the control variable over the following sequence of values: 2
, 5
, 8
, 11
, 14
, 17
, 20
for (var j =2; j <=20; j +=3 )
f) Vary the control variable over the following sequence of values: 99
, 88
, 77
, 66
, 55
, 44
, 33
, 22
, 11
, 0
.
for (var j =99; j >=0; j -=11 )
Not using the proper relational operator in the loop-continuation condition of a loop that counts downward (e.g., using i <= 1 in a loop that counts down to 1) is usually a logic error that will yield incorrect results when the program runs.
The next two scripts demonstrate the for
repetition statement. Figure 6.5 uses the for
statement to sum the even integers from 2
to 100
. Note that the increment expression adds 2
to the control variable number
after the body executes during each iteration of the loop. The loop terminates when number
has the value 102
(which is not added to the sum).
Note that the body of the for
statement in Fig. 6.5 actually could be merged into the rightmost (increment) portion of the for
header by using a comma, as follows:
for (var number = 2; number <= 100; sum += number, number += 2)
;
Similarly, the initialization sum = 0
could be merged into the initialization section of the for
statement.
Although statements preceding a for statement and in the body of a for statement can often be merged into the for header, avoid doing so, because it makes the program more difficult to read.
For clarity, limit the size of control-statement headers to a single line, if possible.
The next example computes compound interest (compounded yearly) using the for
statement. Consider the following problem statement:
A person invests $1000.00 in a savings account yielding 5 percent interest. Assuming that all the interest is left on deposit, calculate and print the amount of money in the account at the end of each year for 10 years. Use the following formula to determine the amounts:
a = p(1 +r )n
where
p is the original amount invested (i.e., the principal)
r is the annual interest rate
n is the number of years
a is the amount on deposit at the end of the n th year.
This problem involves a loop that performs the indicated calculation for each of the 10 years the money remains on deposit. Figure 6.6 presents the solution to this problem, displaying the results in a table.
Lines 16–18 declare three variables and initialize principal
to 1000.0
and rate
to .05
. Lines 20–21 write an XHTML <table>
tag, and lines 22–23 write the caption
that summarizes the table’s content. Lines 24–25 create the table’s header section (<thead>
), a row (<tr>
) and a column heading (<th>
) containing “Year
.” Lines 26–28 create a table heading for “Amount on deposit
” and write the closing </tr>
and </thead>
tags.
The for
statement (lines 31–37) executes its body 10 times, incrementing control variable year
from 1 to 10 (note that year
represents n in the problem statement). Java-Script does not include an exponentiation operator. Instead, we use the Math
object’s pow
method for this purpose. Math.pow(x, y)
calculates the value of x
raised to the y
th power. Method Math.pow
takes two numbers as arguments and returns the result.
Line 33 performs the calculation using the formula given in the problem statement. Lines 34–36 write a line of XHTML markup that creates another row in the table. The first column is the current year
value. The second column displays the value of amount
. Line 39 writes the closing </tbody>
and </table>
tags after the loop terminates.
Line 35 introduces the Number object and its toFixed method. The variable amount
contains a numerical value, so JavaScript represents it as a Number
object. The toFixed
method of a Number
object formats the value by rounding it to the specified number of decimal places. In line 35, amount.toFixed(2)
outputs the value of amount with two decimal places.
Variables amount
, principal
and rate
represent numbers in this script. Remember that JavaScript represents all numbers as floating-point numbers. This feature is convenient in this example, because we are dealing with fractional parts of dollars and need a type that allows decimal points in its values.
Unfortunately, floating-point numbers can cause trouble. Here is a simple example of what can go wrong when using floating-point numbers to represent dollar amounts (assuming that dollar amounts are displayed with two digits to the right of the decimal point): Two dollar amounts stored in the machine could be 14.234 (which would normally be rounded to 14.23 for display purposes) and 18.673 (which would normally be rounded to 18.67 for display purposes). When these amounts are added, they produce the internal sum 32.907, which would normally be rounded to 32.91 for display purposes. Thus your printout could appear as
but a person adding the individual numbers as printed would expect the sum to be 32.90. You have been warned!
Occasionally, an algorithm will contain a series of decisions in which a variable or expression is tested separately for each of the values it may assume, and different actions are taken for each value. JavaScript provides the switch
multiple-selection statement to handle such decision making. The script in Fig. 6.7 demonstrates three different CSS list formats determined by the value the user enters.
Line 12 in the script declares the variable choice
. This variable stores the user’s choice, which determines what type of XHTML list to display. Lines 13–14 declare variables startTag
and endTag
, which will store the XHTML tags that will be used to create the list element. Line 15 declares variable validInput
and initializes it to true
. The script uses this variable to determine whether the user made a valid choice (indicated by the value of true
). If a choice is invalid, the script sets validInput
to false
. Line 16 declares variable listType
, which will store an h1
element indicating the list type. This heading appears before the list in the XHTML document.
Lines 18–19 prompt the user to enter a 1
to display a numbered list, a 2
to display a lettered list and a 3
to display a list with roman numerals. Lines 21–40 define a switch statement that assigns to the variables startTag
, endTag
and listType
values based on the value input by the user in the prompt
dialog. We create these different lists using the CSS property list-style-type, which allows us to set the numbering system for the list. Possible values include decimal
(numbers—the default), lower-roman
(lowercase Roman numerals), upper-roman
(uppercase Roman numerals), lower-alpha
(lowercase letters), upper-alpha
(uppercase letters), and several others.
The switch
statement consists of a series of case labels and an optional default case. When the flow of control reaches the switch
statement, the script evaluates the controlling expression (choice
in this example) in the parentheses following keyword switch
. The value of this expression is compared with the value in each of the case
labels, starting with the first case
label. Assume that the user entered 2
. Remember that the value typed by the user in a prompt
dialog is returned as a string. So, the string 2
is compared to the string in each case
in the switch
statement. If a match occurs (case "2":
), the statements for that case
execute. For the string 2
(lines 29–32), we set startTag
to an opening ol
tag with the style property list-style-type
set to upper-alpha
, set endTag
to "</ol>"
to indicate the end of an ordered list and set listType
to "<h1>Lettered List</h1>"
. If no match occurs between the controlling expression’s value and a case
label, the default
case executes and sets variable validInput
to false
.
The break
statement in line 32 causes program control to proceed with the first statement after the switch
statement. The break
statement is used because the case
s in a switch
statement would otherwise run together. If break
is not used anywhere in a switch
statement, then each time a match occurs in the statement, the statements for all the remaining case
s execute.
Next, the flow of control continues with the if
statement in line 42, which tests variable validInput
to determine whether its value is true
. If so, lines 44–49 write the list-Type
, the startTag
, three list items (<li>
) and the endTag
. Otherwise, the script writes text in the XHTML document indicating that an invalid choice was made (line 52).
Each case
can have multiple actions (statements). The switch
statement is different from others in that braces are not required around multiple actions in a case
of a switch
. The general switch
statement (i.e., using a break
in each case
) is flowcharted in Fig. 6.8. [Note: As an exercise, flowchart the general switch
statement without break
statements.]
The flowchart makes it clear that each break
statement at the end of a case
causes control to exit from the switch
statement immediately. The break
statement is not required for the last case
in the switch
statement (or the default
case, when it appears last), because program control automatically continues with the next statement after the switch
statement.
Forgetting a break statement when one is needed in a switch statement is a logic error.
Provide a default case in switch statements. Cases not explicitly tested in a switch statement without a default case are ignored. Including a default case focuses you on processing exceptional conditions. However, there are situations in which no default processing is needed.
Although the case clauses and the default case clause in a switch statement can occur in any order, it is clearer (and more common) to place the default clause last.
In a switch statement, when the default clause is listed last, its break statement is not required. Some programmers include this break for clarity and for symmetry with other cases.
Note that having several case
labels listed together (e.g., case 1: case 2:
with no statements between the cases) performs the same set of actions for each case.
The do…while repetition statement is similar to the while
statement. In the while
statement, the loop-continuation test occurs at the beginning of the loop, before the body of the loop executes. The do…while
statement tests the loop-continuation condition after the loop body executes—therefore, the loop body always executes at least once. When a do…while
terminates, execution continues with the statement after the while
clause. Note that it is not necessary to use braces in a do…while
statement if there is only one statement in the body. However, the braces usually are included, to avoid confusion between the while
and do…while
statements. For example,
while ( condition )
normally is regarded as the header to a while
statement. A do…while
statement with no braces around a single-statement body appears as
do
statement
while ( condition );
which can be confusing. The last line—while
( condition );—may be misinterpreted as a while
statement containing an empty statement (the semicolon by itself). Thus, to avoid confusion, the do…while
statement with a one-statement body is often written as follows:
do
{
statement
} while ( condition );
Some programmers always include braces in a do…while statement even if they are not necessary. This helps eliminate ambiguity between the while statement and the do…while statement containing a one-statement body.
Infinite loops are caused when the loop-continuation condition never becomes false in a while, for or do…while statement. To prevent this, make sure that there is not a semicolon immediately after the header of a while or for statement. In a counter-controlled loop, make sure that the control variable is incremented (or decremented) in the body of the loop. In a sentinel-controlled loop, make sure that the sentinel value is eventually input.
The script in Fig. 6.9 uses a do…while
statement to display each of the six different XHTML heading types (h1
through h6
). Line 12 declares control variable counter
and initializes it to 1
. Upon entering the do…while
statement, lines 15–17 write a line of XHTML text in the document. The value of control variable counter
is used to create the starting and ending header tags (e.g., <h1>
and </h1>
) and to create the line of text to display (e.g., This is an h1 level head
). Line 18 increments the counter
before the loop-continuation test occurs at the bottom of the loop.
The do…while
flowchart in Fig. 6.10 makes it clear that the loop-continuation test does not occur until the action executes at least once.
The break and continue statements alter the flow of control. The break
statement, when executed in a while
, for
, do…while
or switch
statement, causes immediate exit from the statement. Execution continues with the first statement after the structure. The break
statement is commonly used to escape early from a loop or to skip the remainder of a switch
statement (as in Fig. 6.7). Figure 6.11 demonstrates the break
statement in a for
repetition statement.
During each iteration of the for
statement in lines 14–20, the script writes the value of count
in the XHTML document. When the if
statement in line 16 detects that count
is 5
, the break
in line 17 executes. This statement terminates the for
statement, and the program proceeds to line 22 (the next statement in sequence immediately after the for
statement), where the script writes the value of count
when the loop terminated (i.e., 5
). The loop executes line 19 only four times.
The continue
statement, when executed in a while
, for
or do…while
statement, skips the remaining statements in the body of the statement and proceeds with the next iteration of the loop. In while
and do…while
statements, the loop-continuation test evaluates immediately after the continue
statement executes. In for
statements, the increment expression executes, then the loop-continuation test evaluates. This is the one case in which for
and while
differ. Improper placement of continue
before the increment in a while
may result in an infinite loop.
Figure 6.12 uses continue in a for
statement to skip the document.writeln
statement in line 20 when the if
statement in line 17 determines that the value of count
is 5
. When the continue
statement executes, the script skips the remainder of the for
statement’s body. Program control continues with the increment of the for
statement’s control variable, followed by the loop-continuation test to determine whether the loop should continue executing.
Some programmers feel that break and continue violate structured programming. They do not use break and continue, because the effects of these statements can be achieved by structured programming techniques.
The break and continue statements, when used properly, perform faster than the corresponding structured techniques.
There is a tension between achieving quality software engineering and achieving the best-performing software. Often, one of these goals is achieved at the expense of the other. For all but the most performance-intensive situations, the following rule of thumb should be followed: First make your code simple, readable and correct; then make it fast and small, but only if necessary.
break
and continue
StatementsThe break
statement can break out of an immediately enclosing while
, for
, do…while
or switch
statement. To break out of a nested set of structures, you can use the labeled break statement. This statement, when executed in a while
, for
, do…while
or switch
statement, causes immediate exit from that statement and any number of enclosing repetition statements; program execution resumes with the first statement after the enclosing labeled statement (a statement preceded by a label). The labeled statement can be a block (a set of statements enclosed in curly braces, {}
). Labeled break
statements commonly are used to terminate nested looping structures containing while
, for
, do…while
or switch
statements. Figure 6.13 demonstrates the labeled break
in a nested for
statement.
The labeled block (lines 12–28) begins with a label (an identifier followed by a colon). Here, we use the label stop:
. The block is enclosed between the braces at the end of line 12 and in line 28, and includes both the nested for
statement starting in line 13 and the document.writeln
statement in line 27. When the if
statement in line 17 detects that row
is equal to 5
, the statement in line 18 executes. This statement terminates both the for
statement in line 15 and its enclosing for
statement in line 13, and the program proceeds to the statement in line 30 (the first statement in sequence after the labeled block). The inner for
statement executes its body only four times. Note that the document.writeln
statement in line 27 never executes, because it is included in the labeled block and the outer for
statement never completes.
The continue
statement proceeds with the next iteration (repetition) of the immediately enclosing while
, for
or do…while
statement. The labeled continue statement, when executed in a repetition statement (while
, for
or do…while
), skips the remaining statements in the structure’s body and any number of enclosing repetition statements, then proceeds with the next iteration of the enclosing labeled repetition statement (a repetition statement preceded by a label). In labeled while
and do…while
statements, the loop-continuation test evaluates immediately after the continue
statement executes. In a labeled for
statement, the increment expression executes, then the loop-continuation test evaluates. Figure 6.14 uses the labeled continue
statement in a nested for
statement to cause execution to continue with the next iteration of the outer for
statement.
The labeled for
statement (lines 13–24) starts with the nextRow
label in line 12. When the if
statement in line 19 in the inner for
statement detects that column
is greater than row
, line 20 executes and program control continues with the increment of the control variable of the outer for
statement. Even though the inner for
statement counts from 1 to 10, the number of *
characters output on a row never exceeds the value of row
.
So far, we have studied only such simple conditions as count <= 10
, total > 1000
and number != sentinelValue
. These conditions were expressed in terms of the relational operators >
, <
, >=
and <=
, and in terms of the equality operators ==
and !=
. Each decision tested one condition. To make a decision based on multiple conditions, we performed these tests in separate statements or in nested if
or if...else
statements.
JavaScript provides logical operators that can be used to form more complex conditions by combining simple conditions. The logical operators are && (logical AND), || (logical OR) and ! (logical NOT, also called logical negation). We consider examples of each of these operators.
Suppose that, at some point in a program, we wish to ensure that two conditions are both true
before we choose a certain path of execution. In this case, we can use the logical &&
operator, as follows:
if ( gender == 1 && age >= 65 )
++seniorFemales;
This if
statement contains two simple conditions. The condition gender == 1
might be evaluated to determine, for example, whether a person is a female. The condition age >= 65
is evaluated to determine whether a person is a senior citizen. The if
statement then considers the combined condition
gender == 1 && age >=65
This condition is true
if and only if both of the simple conditions are true
. Finally, if this combined condition is indeed true
, the count of seniorFemales
is incremented by 1
. If either or both of the simple conditions are false
, the program skips the incrementing and proceeds to the statement following the if
statement. The preceding combined condition can be made more readable by adding redundant parentheses:
( gender == 1 ) && ( age >=65 )
The table in Fig. 6.15 summarizes the &&
operator. The table shows all four possible combinations of false
and true
values for expression1 and expression2. Such tables are often called truth tables. JavaScript evaluates to false
or true
all expressions that include relational operators, equality operators and/or logical operators.
Now let us consider the ||
(logical OR) operator. Suppose we wish to ensure that either or both of two conditions are true
before we choose a certain path of execution. In this case, we use the ||
operator, as in the following program segment:
if ( semesterAverage >= 90 || finalExam >= 90 )
document.writeln( "Student grade is A" );
This statement also contains two simple conditions. The condition semesterAverage >= 90
is evaluated to determine whether the student deserves an “A” in the course because of a solid performance throughout the semester. The condition finalExam >= 90
is evaluated to determine whether the student deserves an “A” in the course because of an outstanding performance on the final exam. The if
statement then considers the combined condition
semesterAverage >=90 || finalExam >=90
and awards the student an “A” if either or both of the simple conditions are true
. Note that the message "Student grade is A"
is not printed only when both of the simple conditions are false
. Figure 6.16 is a truth table for the logical OR operator (||
).
The &&
operator has a higher precedence than the ||
operator. Both operators associate from left to right. An expression containing &&
or ||
operators is evaluated only until truth or falsity is known. Thus, evaluation of the expression
gender == 1 && age >=65
stops immediately if gender
is not equal to 1
(i.e., the entire expression is false
) and continues if gender
is equal to 1
(i.e., the entire expression could still be true
if the condition age >= 65
is true
). Similarly, the ||
operator immediately returns true
if the first operand is true
. This performance feature for evaluation of logical AND and logical OR expressions is called short-circuit evaluation.
JavaScript provides the !
(logical negation) operator to enable a programmer to “reverse” the meaning of a condition (i.e., a true
value becomes false
, and a false
value becomes true
). Unlike the logical operators &&
and ||
, which combine two conditions (i.e., they are binary operators), the logical negation operator has only a single condition as an operand (i.e., it is a unary operator). The logical negation operator is placed before a condition to choose a path of execution if the original condition (without the logical negation operator) is false
, as in the following program segment:
if ( ! ( grade == sentinelValue ) )
document.writeln( "The next grade is " + grade );
The parentheses around the condition grade == sentinelValue
are needed, because the logical negation operator has a higher precedence than the equality operator. Figure 6.17 is a truth table for the logical negation operator.
In most cases, you can avoid using logical negation by expressing the condition differently with an appropriate relational or equality operator. For example, the preceding statement may also be written as follows:
if ( grade != sentinelValue )
document.writeln( "The next grade is " + grade );
The script in Fig. 6.18 demonstrates all the logical operators by producing their truth tables. The script produces an XHTML table containing the results.
In the output of Fig. 6.18, the strings "false"
and "true"
indicate false
and true
for the operands in each condition. The result of the condition is shown as true
or false
. Note that when you use the concatenation operator with a boolean value and a string, JavaScript automatically converts the boolean value to string "false"
or "true"
. Lines 16–39 build an XHTML table containing the results.
An interesting feature of JavaScript is that most nonboolean values can be converted to boolean true
or false
values. Nonzero numeric values are considered to be true
. The numeric value zero is considered to be false
. Any string that contains characters is considered to be true
. The empty string (i.e., the string containing no characters) is considered to be false
. The value null
and variables that have been declared but not initialized are considered to be false
. All objects (e.g., the browser’s document
and window
objects and JavaScript’s Math
object) are considered to be true
.
Figure 6.19 shows the precedence and associativity of the JavaScript operators introduced up to this point. The operators are shown top to bottom in decreasing order of precedence.