reptile7's JavaScript blog is Andrew Peak's personal technical writing project: it focuses on JavaScript and the analysis of JavaScript scripts, although HTML, CSS, and anything else related to coding for the Web are also fair game.

(1) The document head's rand( ) function, which is almost identical to the rand( ) function in the Primer #20 Script (not the Primer #21 Script, as incorrectly stated in the primer). Primer #20's rand( ) commands were discussed in detail in Blog Entry #36, so there's no need to rehash them here - we'll see below that these commands can be 'unfunctionized' (i.e., they don't need to be in a function) if desired;

(2) The document head's guessnum( ) function, which we'll take up shortly; and

(3) The document body HTML, which largely parallels the corresponding document body code of the last two primer scripts. (In case you were wondering, the "I'm thinking of a number from 1 to 10" header is uneventfully rendered as an h2 element by both MSIE and Netscape in spite of the mismatched closing </h1> tag, as can be shown at the aforelinked Hope College demo site, which does not bother to correct the mismatch.)

The guessnum( ) function

Let's set the stage, shall we? When the document loads, we first generate a random number num whose value runs from 1 to 10 via the rand( ) function, which is triggered by the onLoad event handler in the document <body> tag. We're now ready to guess what that random number is, and we accordingly click the "Guess [the number]" button, which triggers the guessnum( ) function.

Up pops a prompt( ) box that asks, "Your guess?" The user types in a number, which is assigned to the variable guess after the "OK" button is clicked. This brings us to the script's central if...else statement:

The if code is executed if the user guesses the random number correctly; for an incorrect guess, the else code is executed.

Without any comment at all on Joe's part, the if conditional statement invokes the top-level eval( ) function, whose purpose here is to ensure that guess is interpreted as a number data type and not as a string data type (recall from the previous post that prompt( ) outputs are strings). The eval( ) function evaluates code in the form of a string; for example, eval("31%10") would return 1, and with respect to the Primer #22 Script, eval("document.myform.b1.type") would return button.

As noted in Netscape's eval( ) documentation, the eval( ) function evaluates numerical string literals to give their number equivalents. So, getting back to our guessing game, suppose the user types 5 into the prompt( ) box; 5 is outputted/assigned to guess as a string (i.e., it's now "5"), and then eval(guess)=eval("5") reconverts "5" to 5, the number.

The if statement then compares the eval(guess) return with the value of num from the rand( ) function to see if they are equal; this comparison raises a few interesting-if-not-quite-crucial issues:

(1) With respect to variable scope, both the now and num variables are initialized inside of the rand( ) function and thus qualify as local (not global) variables; before the fact, then, one might expect the guessnum( ) function to not recognize num and perhaps throw an error at this point, and yet it is clear that num undergoes 'function crossing' without any problems, as you can see for yourself at the Hope College demo page.

(2) Netscape's "Variable Scope" documentation also states, "[Y]ou must use var to declare a variable inside a function." Neither now, num, nor guess is declared via the var keyword, but this again poses no problems vis-à-vis the script's effect. (Looking back, I see that the assignment answer scripts for Primers #14, #20, and #21 also feature local variables that are not declared with var.)

(3) If we're going to use the == equal comparison operator here, then use of the eval( ) function is in fact not necessary. According to Netscape's "Comparison Operators" documentation: "The standard equality operators (== and !=) compare two operands without regard to their type...When type conversion is needed, JavaScript converts String, Number, Boolean, or Object operands as follows[:] When comparing a number and a string, the string is converted to a number value." It follows that in the eval( )-less statement:

if (guess == num) {alert("YOU GUESSED IT!!"); rand( );}

the browser's JavaScript engine will automatically convert guess to a number, so no 'evaluation' of guess is required.

(The preceding Netscape reference notes that JavaScript also has a === "strict equal" binary comparison operator that returns true only if its operands are equal and of the same type; the use of === in guessnum( )'s if statement:

if (eval(guess) === num) {alert("YOU GUESSED IT!!"); rand( );}

would indeed require the eval( ) function to convert guess to a number.)

Anyway, if eval(guess) and num are equal, then the if alert( ) box pops up announcing "YOU GUESSED IT!!", followed by a rand( ) function call, which Joe does not discuss and which generates a new random number if the user wants another go at the game. As far as I am aware, this is the first time in the HTML Goodies JavaScript Primers series that a function is called via a basic function_name( ) command (as opposed to using an event handler).

If eval(guess) and num are not equal, then the else alert( ) box pops up announcing "No. Try again." To make subsequent guesses, the user reclicks the "Guess [the number]" button and the guessnum( ) process starts all over again.

Note that alert("No. Try again."); is not surrounded by braces, which can be omitted for a solitary if or else command.

Other code possibilities

As noted above, the random number code does not need to be functionized. Consider, for example, the following script:

After a first play of the game, the random number is refreshed by reloading the page via a history.go(0) command in the if code. I've also included a guessnum2( ) function call* in the else code - this sets up a prompt( )-alert( ) loop** for incorrect guesses so that you don't need to click the "Guess the number" button over and over. (*Netscape's "Calling Functions" documentation notes, "A function can...be recursive, that is, it can call itself.")(**I recognize that some users might find this annoying; the else guessnum2( ) function call can be left out if desired.)

Relatedly, the random number code can alternatively be brought into the guessnum( ) function if, again, guessnum( ) includes a looping mechanism that bypasses the random number code; for example:

The while loop code says, "As long as guess is not equal to num [!= is the 'not equal' comparison operator], then execute the following code in {braces} repeatedly, but if guess becomes equal to num, then stop"; note that the browser skips over the loop's if statement if guess is not equal to num. We will revisit the while loop topic when we discuss Primer #25.

The Primer #22 Assignment

In the Primer #22 Assignment, Joe asks the reader to modify the Primer #22 Script so that it indicates whether the user's guess at the random number is too high, too low, or just right. Towards this end, the assignment answer script employs in a corresponding guessnum( ) function a series of if statements making use of the ==, > (is greater than), and < (is less than) comparison operators:

In none of the if statements above is the eval( ) function actually necessary to convert guess to a number; > and < comparisons are like == comparisons in this regard.

Significantly, note that if statement #1 (the "just right" comparison) does not have a rand( ) function call for renewing the random number num, and there's a reason for this: if it did include a rand( ); command, then when the user guesses correctly, the "YOU GUESSED MY NUMBER!!" alert( ) message will in most cases be followed by either a "Too high!" or a "Too low!" alert( ) message. Bear in mind that even if if statement #1's condition is true, the browser isn't finished with the guessnum( ) function and is still going to check if statements #2 and #3. Evidently and somewhat unintuitively, a rand( ) function call in if statement #1 creates a new random number num, ready for use, before the browser acts on if statement #2, and if the new num is different than the old num, then either if statement #2's condition or if statement #3's condition will be true, resulting in a second alert( ) message.

There are at least three simple workarounds for this problem:(1) Renew the random number num with a history.go(0) command in if statement #1, as in the guessnum2( ) function above;(2) Put a rand( ) function call in if statement #1 but delay its execution via the setTimeout( ) method of the window object, e.g., window.setTimeout("rand( )",2000); or(3) Reorder the guessnum( ) if statements, putting the "just right" comparison last.

Finally, the assignment does make a useful larger point: a 'multiple-choice' script leading to three or more outcomes can often be crafted with a set of if statements and without any else statements.We'll conclude our if...else series in the next post with a discussion of HTML Goodies' JavaScript Primers #23, in which we'll use if...else statements to display random text strings and images.