Destiny is no matter of chance. It is a matter of choice. It is not a thing to be waited for, it is a thing to be achieved.William Jennings Bryan
"Contrariwise," continued Tweedledee, "if it was so, it might be; and if it were so, it would be; but as it isn't, it ain't. That's logic."Lewis Carroll
Through the Looking Glass
So far, all the JavaScript code that you have written has been executed unconditionally. This means that the browser carried out statements in a set order, one after another. Given different inputs, your program might produce different results, but it always went through the same steps and produced output of the same form. Event-driven pages provided some variety, because they contained statements that users must initiate by interacting with buttons and boxes. However, once an event was triggered, the JavaScript code associated with the event executed unconditionally.
Many programming tasks, however, require code to react differently in response to varying circumstances or conditions. This capability is called conditional control. For example, consider a program that converts a student's numerical average to a letter grade. Depending upon the particular student's average, the program would need to assign a different letter grade (90 to 100 would be an A, 80 to 89 would be a B, and so on). Similarly, you might want to design a page that uses a random die roll to determine which of several images to display. In this chapter, you will be introduced to the if statement, which is used to incorporate conditional execution into JavaScript programs. Depending on whether some condition is met, an if statement can choose among alternative sequences of code to execute - or can even choose to execute no code at all.
Conditional execution refers to a program's ability to execute a statement or sequence of statements only if some condition holds true. The simplest form of conditional statement involves only one possible action. For example, if you employ a variable to represent a student's grade on a test, you might want your program to recognize a failing grade and warn the student. However, conditional execution can also involve alternatives that execute in response to the same or related conditions. That is, a program can take one action if some condition is true, but take a different action if the condition is not true (the code that executes in the latter instance is called the else case). For example, you might want to display one message for a failing grade and another message for a passing grade. JavaScript if statements enable you to perform both these types of conditional execution.
The general form of an if statement is as follows, where the else case is optional:
relational operator | comparison defined by the operator |
---|---|
== | equal to |
!= | not equal to |
< | less than |
<= | less than or equal to |
> | greater than |
>= | greater than or equal to |
Figure 11.1: Relational operators in JavaScript.
The Boolean test at the beginning of an if statement determines which (if any) code will be executed. If th test succeeds (evaluates to true), then the code that follows inside curly-braces is executed. If the test fails (evaluates to false) and there is an else case, then the code that follows the else inside curly-braces is executed. Note that if the test fails and there is no else case, then no statements are executed, and the program moves on to the next statement following the if.
Figure 11.2 depicts three different if statements related to student grades. When executing the first if statement, the browser would evaluate the test to see whether the value of variable grade is less than 60. If so, the browser calls the alert function to display the warning, "You failed! Time to hit the books." However, if grade is greater than or equal to 60, then the statement inside the curly-braces is skipped over. The second example demonstrates that an if statement can control the execution of entire sequences of statements. If the test succeeds (grade is less than 60), then the statements inside the curly-braces are executed in order. In this case, the statements compute the difference between a passing grade and the grade earned, then incorporate that value in an alert message. The third example adds an else case to the if statement, ensuring that a message is displayed regardless of grade's value. If the grade is less than 60, the browser will display the difference between a passing grade and the earned grade, as before. If not, then the message, "Congratulations, you passed." is displayed.
|
Figure 11.2: Example if statements.
Web browsers ignore indentation and spacing when executing JavaScript code, so these features are irrelevant from the browser's perspective. However, from the programmer's perspective, indentation and spacing are vitally important. When you write an if statement, it is important to format the code so that its structure is apparent. Otherwise, another programmer modifying your code might introduce errors by misinterpreting which statements are controlled by the if and which are not. For example, in Figure 11.2's if statements, the closing curly-brace is aligned with the beginning if, whereas all statements inside the curly-braces are indented. This format emphasizes where each if statement begins and ends, enabling others to read and understand the code more easily. Technically speaking, the curly-braces in an if-statement are optional when there is only one statement to be executed conditionally. However, we strongly recommend that you include the curly-braces in every if statement you write. When all if statements look the same, it is easier for you to code them correctly. The consistent use of curly-braces also helps prevent subtle errors when code is modified. |
The page in Figure 11.3 contains a text box in which to enter a grade and a button for initiating the function ShowMessage. ShowMessage, which displays an alert if the user entered a grade that is less than 60, incorporates the first if statement from Figure 11.2.
|
Figure 11.3: Web page that demonstrates an if statement.
Figure 11.4: Appearance of Web page from Figure 11.3 (ifdemo.html).
EXERCISE 11.1: Enter the ifdemo.html text from Figure 11.3 into a new Web page. Load this page and then describe its behavior when you enter various grades in the text box.Once you have done this, modify the page by replacing the if statement in the ShowMessage function with the third if statement example from Figure 11.2. Load this modified page and describe its behavior when you enter various grades.
EXERCISE 11.2: In the winter, weather reports often refer to the wind-chill factor, a measurement that combines actual temperature and wind speed to provide an estimate of the temperature experienced by an exposed human being. If the wind speed is 3 miles per hour or less, then the wind is not considered a factor-i.e., the wind-chill is the same as the actual temperature. If the wind speed exceeds 3 miles per hour, however, meteorologists use a complex formula to compute the wind-chill. Assuming that temperature stores the actual temperature (in degrees Fahrenheit) and windSpeed stores the wind speed (in miles per hour), we can calculate the wind-chill factor using the following JavaScript code:
if (windSpeed <= 3) { windChill = temperature; } else { windChill = 35.74 + 0.6215*temperature + (0.4275*temperature - 35.75)*Math.pow(windSpeed, 0.16); } Create a Web page named chill.html that computes the wind-chill factor for a given temperature and wind speed. The user should enter a temperature and wind speed via text boxes, then click a button to view the corresponding wind-chill factor in a separate text box. As part of your page, you should define a function named WindChill that accepts the temperature and wind speed as inputs and returns the wind-chill factor.
Once you have completed your page, use it to determine the wind-chill factors for the following weather conditions:
wind = 2 temp = 30 wind = 5 temp = 18 wind = 12 temp = 45 wind = 30 temp = 10
Recall from Chapter 9 that values returned from text boxes or text areas are always strings. If you wish to treat a value obtained from a text box or text area as a number, you must use the parseFloat function to convert the string to its numeric equivalent. As we have established, forgetting to parseFloat such values can introduce subtle errors; this holds true when referencing the contents of text boxes and text areas in if statements. For example, consider the following if statement, which is intended to determine whether a person is old enough to vote (i.e., whether an age entered in a text box is greater than or equal to 18): When certain ages are entered in the text box, this code may appear to behave correctly. However, if you test the code using numerous inputs, you may obtain surprising results. For example, a 9 year old will be considered old enough to vote, but a 100 year old will not! The problem is that, without a call to parseFloat, the browser treats the contents of the text box as a string. Thus, when the if test is evaluated, the test is comparing a string value (the age from the text box) with a number value (18). In situations where a test must compare values of mixed data types, the browser automatically converts the number value into a string and then performs string comparison. Since strings are compared character by character, "9" is considered to be greater than "18" ("9" > "1"), and "100" is considered to be less than "18" (the first characters are identical, so the comparison moves to the second character, where "0" < "8"). To avoid this type of error, always parseFloat the contents of a text box or text area if you intend to treat the contents as a number. |
EXERCISE 11.3: In Chapter 9, you created a magic.html page that simulated the behavior of a magic 8-Ball (EXERCISE 9.7). As written, your page completely ignores the user's question and picks a response at random. In this exercise, modify magic.html so that it is less obvious that the users' questions are irrelevant to the program's execution. Add an if statement to your JavaScript code that determines whether the user entered a question. If not (i.e., the text area contains the empty string), then an alert box should appear and remind the user to enter a question. However, if the user did enter a question (i.e., the text area is not empty), the page should proceed as before and display a randomly selected answer.
Often, programming tasks require code that responds to more than one condition. Since an if statement is itself a JavaScript statement, programmers can attach multiple conditions to the same set of JavaScript statements by nesting one if statement inside another. In fact, nesting if statements can be a highly effective way of structuring complex code.
For example, consider the wind-chill calculation you implemented in EXERCISE 11.2. Technically, the formula for computing wind-chill is defined only for temperatures at or below 50 degrees Fahrenheit. When the temperature is above 50 degrees, wind-chill is not considered meaningful. If we decide to handle this condition in the WindChill function, we can do so by nesting the existing code inside an if statement that determines whether the temperature is a valid one for computing wind-chill. If the temperature is less than or equal to 50, then the code for calculating the appropriate value should be executed as before. If not, then an alert box notifying the user of the error should be displayed, and the wind-chill should be set to NaN, signifying that it is not defined. Figure 11.5 depicts an example of nested if statements that accomplish this task.
Figure 11.5: Generalized code for computing wind chill.
EXERCISE 11.4: Modify your chill.html page so that utilizes the nested if statements from Figure 11.5. In addition to displaying the warning in an alert box, your WindChill function should return NaN when the temperature is greater than 50.
In its simplest form, an if statement determines whether or not to execute a sequence of statements. For instance, the first if statement example in Figure 11.2 displayed a message on the condition that the value stored in variable grade was less than 60, but did nothing otherwise. When an if statement includes an else case, the statement decides between executing two alternative sections of code; this was demonstrated in the third example from Figure 11.2, which displayed different messages for passing and failing grades. By nesting if statements inside each other, it becomes possible to select from among more than two alternatives. For example, your modified wind-chill page recognized three different possibilities: (1) the temperature was greater than 50, (2) the temperature was less than or equal to 50 and the wind speed was less than or equal to 3, and (3) the temperature was less than or equal to 50 and the wind speed was greater than 3. Now, let us examine a slightly different type of nested if statement. Imagine that you wanted to extend the grades example so that the code could differentiate among three classes of grades: failing grades, passing grades less than 90, and grades greater than or equal to 90. The nested if statements in Figure 11.6 would accomplish this task.
Figure 11.6: Nested if statements for differentiating three classes of grades.
Nested if-else structures such as the one in Figure 11.6 are known as cascading if-else statements, because control cascades down the statement like water down a waterfall. The top-most test is evaluated first-in this case: (grade < 60). If this test succeeds, then the corresponding statements are executed, and program control moves to the next statement following the cascading if. If the test fails, then control cascades down to the next if test-in this case: (grade < 90). In general, control cascades down the statement from one test to another until one succeeds or the end of the statement is reached.
When it is necessary to handle a large number of alternatives, cascading if-else statements can become cumbersome and unwieldy. This is because each nested if-else statement introduces another level of indentation and curly-braces, causing the code to look cluttered. Fortunately, programmers can write more concise, clearer cascading if-else statements by adopting a slightly different notation. The left-hand side of Figure 11.7 depicts a set of nested if-else statements that determine a student's letter grade using a traditional grading system. On the right is an equivalent section of code that is much easier to read. This cleaner notation omits some redundant curly-braces and indents each case an equal amount. Using this notation, it is easier to discern that there are five alternatives, each assigning a letter grade on the basis of grade's value.
EXERCISE 11.5: Augment your grades.html page from Chapter 9 by inserting a cascading if-else statement similar to the one on the right-hand side of Figure 11.7. The modified page should display the student's class average in one text box and the corresponding letter grade in another. For example, if the student's average was calculated to be 85.5, then the corresponding text boxes might show:
An if statement is different from other JavaScript statements we have studied in that it does not perform a particular task in and of itself. Instead, it is known as a control statement, since its purpose is to control the execution of other statements. When solving a problem, it is usually fairly easy for programmers to recognize that an if statement is required. If the program needs to make any choices during execution - i.e., the code should react differently under different circumstances - then you should include some version of an if statement.
|
The Web page in Figure 11.7 contains a button and an image of a single die (initially displaying one dot on its face). When a user clicks the button, the function Roll is called to simulate the roll of a 6-sided die. Roll uses the RandomInt function from random.js to obtain a random integer value between one and six, which represents the result of a random die roll. The function then replaces the die image on the page with the one corresponding to that roll. A cascading if-else statement is used to select the appropriate image - for example, http://www.creighton.edu/~csc107/Images/die4.gif corresponds to a roll of 4.
![]() |
Figure 11.8: Web page that uses a cascading if-else to control an image.
Figure 11.9: Appearance of Web page from Figure 11.8 (dice.html).
EXERCISE 11.6: Enter the dice.html text from Figure 11.8 into a new Web page. Load this page and click the button repeatedly to verify that all 6 die faces are obtainable.You may notice a slight delay the first time a particular die face is displayed. This is because the image file is stored on a remote Web server and must be downloaded to your computer before it displays. Once downloaded, the image file is cached by the browser (stored locally in fast memory) so that subsequent displays are virtually instantaneous.
EXERCISE 11.7: Although the cascading if-else statement in dice.html is effective, it is also repetitive and tedious. In each case, the image is assigned a new source file corresponding to the value of the die roll. To simplify the code, we can replace the entire if-else structure with a single assignment that identifies the appropriate file name on the basis of variable roll's current value:document.images.die.src = "http://www.creighton.edu/~csc107/Images/die" + roll + ".gif"; Replace the entire cascading if-else statement with this single assignment and verify that the page behaves as before.
EXERCISE 11.8: Add a second die image to your dice.html page so that the two dice appear side-by-side. When the user clicks the button, both die images should be randomly selected and displayed on the page. Note: you will need to add a second IMG tag to the BODY of the page and add code to the Roll function so that the second IMG is also assigned a random SRC file.
Many scientific applications involve observing phenomena and keeping track of how many times certain events occur. For example, a particle physicist might want to count the number of atomic collisions that take place within a certain time period, whereas a biologist might want to count the number of encounters between animals at an oasis over the course of a day. Similarly, it is possible that users of a particular computer program would wish to record the number of times a certain event occurs within an application. In computer science terminology, any variable that is used to record occurrences of an event is known as a counter. Before it begins tallying, a counter must have an initial value of zero. Then, each time the specified event occurs, the value of the counter is incremented (increased by one). At the end of the observation period, the value stored in the counter represents the number of times that the desired event took place.
EXERCISE 11.9: Add a text box to your dice.html page (below the button) that serves as a counter, keeping track of the number of times the user has rolled the dice. Be sure to set the counter variable's initial value to zero and to accompany the text box with an appropriate text label, such as "Number of dice rolls: ". Within the Roll function, you should add code that accesses the counter value and increments it each time the function is called.
EXERCISE 11.10: Add an additional text box to your dice.html page that serves as a conditional counter, keeping track of the number of times the user rolls doubles (i.e., two identical die faces are displayed on the page). Your text box should appear below the counter you added in Exercise 11.9 and should be accompanied by an appropriate label. Within the Roll function, you should add an if statement that checks whether the die rolls are identical and, if so, increments the doubles counter in the text box.Note: Statistically speaking, doubles should occur 1/6th of the time that the dice are rolled. This is due to the fact that 6 out of the 36 possible dice combinations are doubles. After a reasonable number of rolls, is your doubles count roughly 1/6th of the total number of rolls?
EXERCISE 11.11: Imagine that users of your dice.html page would like to perform repeated experiments with the dice simulator. It would greatly help these users if they were able to reset the roll and double counts within the page. You may note that simply reloading the page does not suffice-the values in the text boxes are retained when you click "Reload" in the browser. It is possible to reset the counters by completely reloading the page -- i.e., by clicking in the browser's Address box and hitting enter. However, this is a rather tedious process, especially if users wish to perform numerous experiments using the counters. A better solution would be to add another button to the page labeled "Reset counters". When the user clicks this button, the contents of the two text boxes should be reset to 0. Add such a button to your page and verify that it behaves as desired.
So far, all the if statements you have written have involved simple tests. Each test contained a single comparison using one of the Boolean operators == (equal to), != (not equal to), < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to). For example, the simple test in the if statement below involves evaluating the sum of two variables, roll1 and roll2. If the sum is eight, then the Boolean expression (roll1 + roll2 == 8) will evaluate to true, and the code inside the if statement will be executed.
In more complex applications, however, simple comparisons between two values may not be sufficient. Suppose, for example, that you wanted to count the number of times that both die faces in dice.html display four dots (we call this a 4-4 combination). Simply testing the sum of the two die faces would not suffice, since this would not distinguish between 4-4 and other combinations that total 8, such as 3-5 and 2-6. Instead, the values of both die faces must be tested to make sure they are both 4s.
One option for creating this type of two-part test is to nest one if statement inside another. Since the browser evaluates the nested if statement only if the outer test succeeds, the code inside the nested if statement is executed precisely when both tests succeed. For example:
Fortunately, JavaScript provides a more natural and compact alternative for expressing multi-part tests. The "&&" operator, when placed between two Boolean tests, represents the conjunction of those tests. This operator is referred to as logical AND, because the Boolean expression (TEST1 && TEST2) will evaluate to true only if TEST1 is true and TEST2 is true. For example:
Since "&&" represents conjunction, the Boolean expression (roll1 == 4 && roll2 == 4) will evaluate to true only if both (roll1 == 4) and (roll2 == 4) evaluate to true. That is, the test will succeed if both values are 4s.
Similarly, a disjunction of tests is accomplished in JavaScript using the "||" operator. This operator is referred to as logical OR, because the Boolean expression (TEST1 || TEST2) will evaluate to true if either TEST1 is true or TEST2 is true. For example, the Boolean expression (roll1 == 4 || roll2 == 4) will evaluate to true if either (roll1 == 4) or (roll2 == 4) evaluate to true. That is, the test will succeed if either of the rolls is a 4.
Finally, the negation of a test is accomplished in JavaScript using the "!" operator. This operator is referred to as logical NOT, because the Boolean expression (!TEST) will evaluate to true if TEST is not true. For example, the Boolean expression (!(roll1 == 4 && roll2 == 4)) will evaluate to true if (roll1 == 4 && roll2 == 4) is false. That is, the test will succeed as long as double 4's are not obtained.
The "&&", "||", and "!" operators are known as logical connectives, since programmers use them to build complex logical expressions by connecting simpler logical expressions.
Note that logical connectives can be applied only to two complete Boolean expressions. For example, imagine that you wanted to test whether the first die in dice.html displays either a 3 or a 4. A common beginner's mistake would be to write partial expressions using the logical OR operator, such as (roll1 == 3 || 4). However, in order to test this condition correctly, full comparisons must appear on each side of the logical connective: (roll1 == 3 || roll1 == 4). |
EXERCISE 11.12: In gambling circles, certain dice combinations are given colorful names. For example, the 1-1 combination is snake-eyes (since the single dots suggest eyes), and the 6-6 combination is box-cars (since the parallel rows of dots suggest train tracks). Similarly, the combination of a 3 and 4 (in either order) is known as a natural 7.Add two additional text boxes to your dice.html page, one that keeps track of the combined number of snake-eyes and box-cars and another that keeps track of the number of natural 7s. Hint: you will most likely want to use logical connectives in order to test for these combinations.
Since snake-eyes and box-cars can each be obtained via a single dice combination, you would expect the combined count for snake-eyes and box-cars to be (1/36 + 1/36) = 1/18th of the total number of rolls. Similarly, the number of naturals should be 1/18th of the total tally, since there are two combinations (3-4 and 4-3) out of 36 that yield natural 7s. After a reasonable number of rolls, is the combined count for snake-eyes and box-cars roughly equal to the count of natural 7s? Are each of these counts roughly 1/18th of the total number of rolls?
Supplemental (optional) material and exercises | Solutions to odd numbered exercises |