reptile7's JavaScript blog
Sunday, June 18, 2006
 
The Collective
Blog Entry #42

We soldier on to HTML Goodies' JavaScript Primers #26, "Putting it all together: Functions from a Function." The Primer #26 Script does indeed feature a function calling another function, as we'll see below; "[h]ere's something new!" Joe enthuses as he addresses the relevant code in his script deconstruction. Not quite, Dr. Burns - we actually saw this sort of thing back in the Primer #22 Script, whose guessnum( ) function calls a preceding rand( ) function when guessnum( )'s if condition is true.

The real 'star of the show' in Primer #26 is the built-in, not-part-of-the-DOM JavaScript Array object. We've heretofore discussed or at least given mention to five other built-in JavaScript objects: Date, Function, Math, Number, and String; consult Chapter 1 ("Objects, Methods, and Properties") of Netscape's JavaScript 1.5 Core Reference for a complete list of these objects. In a programming sense (or nonprogramming sense, for that matter), "array" is synonymous with "set" or "collection." In "The Concept" of Primer #26, Joe defines a JavaScript array constituting an Array object as "a variable that contains many values" - a fair-enough description as far as it goes, and similar to what JavaScript Kit says about arrays in its "Understanding and implementing arrays" tutorial - but I for my part prefer the definition that appears in Netscape's JavaScript 1.5 Core Guide: "An array is an ordered set of values that you refer to with a name and an index."

More abstractly, Netscape also says, "Properties and arrays in JavaScript are intimately related; in fact, they are different interfaces to the same data structure." Think of the document object, whose global properties - bgColor, fgColor, title, etc. - collectively compose an array of elements, each with its own value.

The built-in Array object is distinct from host object arrays/collections - e.g., window.frames[i], navigator.plugins[i], document.forms[i], etc. - whose use we introduced many moons ago (check the last third or so of Blog Entry #13, for example) and which Joe briefly discusses in the "Here's a little more on arrays:" section at the end of Primer #26. The Array object and host object arrays have in common a length property, but to the best of my knowledge, none of the methods or other properties of the Array object is applicable to host object arrays.

Disappointingly, there is no information on the Array object, its properties, or its methods on any of HTML Goodies' JavaScript References pages.

The Primer #26 Script

Let's move from theory to practice and check out the Primer #26 Script:

<html><head>
<script type="text/javascript">
states=new Array( );
states[0]="CT";
states[1]="PA";
states[2]="NJ";
states[3]="NY";
states[4]="RI";
num=0;
function pickstate( ) {
now=new Date( );
num=(now.getSeconds( ))%5; }
function whichstate( ) {
pickstate( );
guess="****";
while (states[num] != guess.toUpperCase( )) {
guess=prompt("What's my favorite state: CT, PA, NJ, NY, or RI?");
if (guess.toUpperCase( ) == states[num]) {
alert("That's my favorite state!"); }
else {alert("No, Try again") } } }
</script></head><body><form>
<input type="button" value="Guess" onClick="whichstate( );">
</form></body></html>

Borrowing features from both the Primer #22 Script and the Primer #23 Script, the Primer #26 Script codes a guessing game that asks the user to guess the scriptwriter's "favorite state," which is generated randomly, from a list of states; an appropriate alert( ) message indicates a correct or an incorrect guess. Focusing on the document head code, the Primer #26 Script has three main parts:
(1) The states array;
(2) The pickstate( ) function; and
(3) The whichstate( ) function.

The states array

Before the guessing game is started by clicking the "Guess [my favorite state!]" button, the states array is loaded into memory via the following code:

states=new Array( );
states[0]="CT";
states[1]="PA";
states[2]="NJ";
states[3]="NY";
states[4]="RI";

The first command line, states=new Array( ), declares with a constructor statement a new Array object - specifically and initially, an array of length=0 because Array( ) has no arguments - and assigns it to the identifier states.

The next five statements assign values to the first five elements of the states array. Recall Joe's definition of an array given earlier: "a variable that contains many values." The regular syntax for specifying those variable values is similar to that for host object arrays:

array_name[i] = "some value";
// i is an index number that starts counting at 0

Each value of states is a text string now associated with an index number that will double as a random number later in the script. As you might guess, these five values will be the "favorite state" choices in the guessing game.

There are two other syntaxes we can use to create the states array:

(1) A 'condensed' array syntax that declares and initializes the array via a single statement in which the array element values appear as comma-delimited Array( ) arguments:

states = new Array("CT","PA","NJ","NY","RI");

(2) An array literal syntax that simply lists the array element values as a sequence in square brackets:

states = ["CT","PA","NJ","NY","RI"];

From this form, it should be clear that an array is analogous mathematically to a matrix.

In both cases, the array element values are indexed as they are in the 'expanded' array syntax: states[0] is "CT", states[1] is "PA", etc. All three array syntaxes are nicely summarized at JavaScript Kit's Array object page.

The pickstate( ) function

The now=new Date( ); num=(now.getSeconds( ))%5; code generates a random number num whose value is 0, 1, 2, 3, or 4, these being the possible remainders for divisions using 5 as the divisor; the values of num will double as the index numbers of the states array elements later in the script.

You've probably noticed that num is declared globally after the states array is created. Is the num=0 statement necessary, given that this initial value of num will be overwritten by the pickstate( ) function? Not at all - leave it out.

The whichstate( ) function

Let's get the guessing game rolling. The user clicks the "Guess [my favorite state!]" button, triggering the whichstate( ) function.

The whichstate( ) function begins with a pickstate( ) function call - here's our 'function from a function,' per the primer title - which generates the random number num, as noted above. Perhaps you are thinking, "The pickstate( ) function really shouldn't be necessary - we should be able to put the random number code in the whichstate( ) function," and you would be correct. Moreover, the states array can be created inside the whichstate( ) function, if desired.

The meat of the whichstate( ) function is the following condition-controlled while loop:

while (states[num] != guess.toUpperCase( )) {
guess=prompt("What's my favorite state: CT, PA, NJ, NY, or RI?");
if (guess.toUpperCase( ) == states[num]) {
alert("That's my favorite state!"); }
else {alert("No, Try again") } }

The while condition compares states[num] and guess.toUpperCase( ) using the != not equal comparison operator. This is the first time in the HTML Goodies JavaScript Primers series that Joe uses the != operator and he provides no commentary thereon in the script deconstruction (we for our part first used the != operator in a similar context in Blog Entry #38). In this case, the while condition returns true, and the while loop body is executed repeatedly, as long as states[num] is not equal to guess.toUpperCase( ).

The left operand, states[num], returns a random value of the states array. The states[num] expression coordinates the values of num with the index numbers i of the states[i] array elements by plugging num into the square brackets that follow states[ ]; because num is random, then states[num] is also random.

The right operand applies to the variable guess the self-explanatory toUpperCase( ) method of the String object, which is not listed on the end-of-primer "Click Here For What You've Learned page but which does at least appear in the HTML Goodies JavaScript methods keyword reference; you'll recall that we made use of the corresponding toLowerCase( ) method in Blog Entry #37. Just prior to the while statement, guess is declared/initialized as a string of four asterisks, ensuring that the while condition returns true and that the while loop body is executed by the browser for at least a first iteration; we'll see below that we can lose the guess="****" statement if we recast the while loop as a do...while loop (both while and do...while loops were discussed in the previous post).

With its condition initially true, the while loop then pops up a prompt( ) box that asks the user to guess a state from the five states constituting the states array; the user types in a response, which is assigned to guess. At this point, you can sort out what happens: the while loop's if and else statements handle correct and incorrect guesses, respectively. For a correct guess, the if condition, guess.toUpperCase( ) == states[num], is true and the script displays a "That's my favorite state!" alert( ) message; the while condition is now false and the loop stops. For an incorrect guess, the script displays a "No, Try again" alert( ) message; the while condition is still true and the loop continues.

Putting it all together, we can write the document head code of the Primer #26 Script much more compactly as follows:

<script type="text/javascript">
states = ["CT","PA","NJ","NY","RI"];
function whichstate( ) {
now=new Date( ); num=now.getSeconds( )%5;
do {
guess=prompt("What's my favorite state: CT, PA, NJ, NY, or RI?");
if (guess.toUpperCase( ) == states[num]) alert("That's my favorite state!");
else alert("No, Try again"); }
while (states[num] != guess.toUpperCase( )) }
</script>

The Primer #26 Assignment

For the Primer #26 Assignment, Joe asks the reader to code a 'random link generator,' i.e., a script that takes the user to a random Web page upon clicking a button. The idea here is to create an array of URL string values - array_name[i]="http://www.some_web_page.com" - that for the assignment is to be coordinated with a random number num via a top.location.href=urls[num] statement.

In his assignment answer, Joe somewhat annoyingly uses newurls and not urls for his array identifier, but what I really want to comment on is his use of the top property of the window object. In the "Referencing a Window: window vs. self vs. parent vs. top" section of Blog Entry #18, we noted, "Outside of a frames situation, 'window', 'self', 'parent', and 'top' all refer to the current active window and can be used interchangeably" and that "[i]n most cases, it is not necessary to reference 'window' either as an object or as a property." Consequently, the top reference in the answer script serves no real purpose and we can simply use location.href=newurls[num] (or even just location=newurls[num], short for window.location=newurls[num]) to set up a random link.

Before we move on to Primer #27, I've got a bit more to say about arrays and the Array object, and I'll do that in the next entry.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)