Chapter 2

JScript: The Language


CONTENTS

There are many, many different computer programming languages in use today. Each has its own set of special features, which are highly praised by its fans and vigorously panned by its detractors. If you have worked in more than one language, you are aware that there is a continuum of language styles, ranging from highly structured languages, such as Ada, to more freewheeling ones, such as LISP. Many are associated with specific settings or applications. Ada, for example, is often found in military projects, while LISP is often associated with artificial intelligence. Some languages, such as HTML, the language used to describe the layout of World Wide Web pages, have a well-defined organizational structure, but have very little in the way of traditional program structure (there are no data types, for example).

In trying to understand a new language, it is not only important to master its syntax, it is also vital to appreciate its style-the way in which that language can be used to accomplish specific goals. We have already reviewed the basic goals of JScript in Chapter 1 "What Is JScript?" as well as contrasting it to the more structured Java language. This chapter describes the JScript language from both perspectives. A thorough description of its syntax is given, and some initial concepts on how to structure a JScript program are also introduced. Anyone who has programming experience in almost any modern declarative language, such as C, C++, Perl, or Pascal, will immediately feel at home. In addition, HTML authors who have never programmed will be able rapidly to acquire JScript proficiency.

JScript Syntax

JScript is based on an action-oriented model of the World Wide Web. Elements of a Web page, such as a button or check box, may trigger actions or events. When one of these events occurs, a corresponding piece of JScript code, usually a JScript function, is executed. That function, in turn, is composed of various statements which perform calculations, examine or modify the contents of the Web page, or perform other tasks in order to respond in some way to that event. For example, pressing the Submit button on an online order form might invoke a JScript function that validates the contents of that form to ensure that the user entered all the required information.

In this section, we examine the syntax of JScript from the bottom up. We begin with the most basic concepts of how to write a JScript statement and what that statement does, and progress upward through more complex and powerful structures in subsequent sections, culminating in a detailed discussion of JScript functions and related concepts. Chapter 3 "Events and JScript," explores in greater detail how these elements are tied into Web pages through events.

In general, the elements of a JScript program can be divided into five categories, as follows:

This set of categories is very similar to many other languages. As we examine each of these elements in subsequent sections, we will discover that JScript is somewhat minimalist in its approach. Many familiar elements, such as explicit data types (int, String, REAL), are missing or have been substantially simplified. However, JScript also provides a number of powerful object-oriented constructs which greatly simplify program organization. In this way, JScript has the expressive power of languages such as C or Java, while also having fewer rules to remember.

Variables and Values

One of the main differences between JScript and most other languages is that it does not have explicit data types. There is no way to specify that a particular variable represents an integer, a string, or a floating-point (real) number. Any JScript variable can be any of these-in fact, the same variable can be interpreted differently in different contexts.

All JScript variables are declared using the keyword var. A variable may be initialized, meaning that it is given a value when it is declared, or it may be uninitialized. In addition, multiple variables can be declared on the same line by separating their names with commas. For example, the statements:

var x = 7
var y,z = "19"
var lk = "lucky"

declare a variable named x with initial value 7, an uninitialized variable y and variables named z and lk whose initial values are "19" and "lucky," respectively. It might seem that x is an integer, z and lk are strings, and y is some undefined quantity. In fact, the real story is a little more complicated than this. The value of each variable depends on the context in which it is used. This context is related to the order in which the variables are seen. As you might guess, the expressions:

5 + x
lk + z

evaluate to 12 and "lucky19," seemingly confirming our suspicions about what they really are. However, it is also possible to form the expressions:

lk + x
x + z

which evaluates to "lucky7" and 26, respectively. In the first expression, x has been interpreted as a string, while in the second, z has been interpreted as an integer.

Tip
JScript often attempts to treat all variables within a statement as if they had the same type as the first variable in the statement.

These examples illustrate two critically important points about the JScript language. First, while JScript does not have explicit data types, it does have implicit data types. Second, JScript has a set of conversion rules that allow it to decide how to treat a value based on the context in which it is used. The context is established by reading the expression from left to right. In the expression x + z, for example, x is implicitly a numerical value, so that JScript also attempts to view z as a number and perform the sum numerically. It succeeds, and the expected 26 results.

What would have happened if we had tried x + lk? The x variable occurs first on the left, and is really a number at heart. JScript thus tries to interpret the variable lk as a number, too. This is extremely unlucky, in fact, because "lucky" cannot be converted to a number (while z, the string "19" could). JScript reports an error if asked to evaluate x + lk. To understand JScript variables and values, therefore, it is necessary to understand its set of implicit types and how they may be converted to one another.

Before we enter into these details, let us consider one final example. In all the preceding cases, the uninitialized variable y was never used. What would be the value of an expression such as:

x = z + y

Of course, as in all other programming languages, the result of using an uninitialized variable is never good. Since y has never been given a value, there is no way this expression can be evaluated. It may result in something seemingly innocent, such as x being assigned the value of z, as if y were zero. It may also result in something much more serious, such as the value of x becoming something strange, or, more likely, a JScript error occurring. This leads to the following commonsense rule.

Tip
Initialize all JScript variables to meaningful default values. If a variable has no meaningful default, initialize it to null.

Implicit Data Types in JScript

There are five major implicit data types in JScript. A JScript value may be as follows:

Actually, it would be more correct to say that there are five categories of data type, because it is possible to distinguish two different types of numbers (integers and floating-point numbers), and many different types of JScript objects, functions, and other structured types. In fact, Part II of this book, "JScript Objects," is entirely devoted to explaining the many different JScript objects.

Variables and Variable Names. It is very important to distinguish between variables and their values. The statement x = 10 contains two components: the variable x and the literal value 10. A literal refers to anything that is referred to directly by its actual value. A variable is just an abstraction that provides a way of giving names to values. Thus, the statement x = 10 says, "I am going to refer to the concrete (literal) quantity 10 by the abstract (variable) name x," just as you might say, "I am going to call this lumpy thing I'm sitting on a chair." This also leads to the following important piece of advice.

Caution
It is bad practice to change the implicit data type of a variable. If a variable is initialized to have a certain type (such as string), it should always have that type.

Thus, because we have started out with x = 10, we should make sure that x always has some numeric value. There is no rule that prohibits us from later saying x = "Fortran," but this will generally lead to confusion or programming errors in most cases. No one will stop you from calling that lumpy thing you are sitting on "bacon and eggs," but many of your guests may become confused if you do so.

One final rule about variable names: A valid JScript variable name must begin with a letter or with the underscore character (_). Case is important, so that norl, NoRl, NORL, and _NORL are all valid JScript variable names that refer to different variables.

Numerical Values. There are two numeric types in JScript: integers and floating-point numbers. The rules for specifying both types are almost identical to those of C or C++ or Java. Integers may be specified in base 10 (decimal), base 8 (octal), or base 16 (hexadecimal) formats. The three forms are distinguished as follows, based on the first one or two characters:

Any of the three forms can also start with a plus (+) or minus (-) sign. Thus, -45 is a decimal integer, 017 is an octal integer, and 0x12EF5 is a hexadecimal integer. The minimum and maximum integers that can be used are implementation-dependent, but at least 32 bits should be expected.

Floating-point numbers can be specified in either the standard decimal point (".") format or the engineering E-notation. Typical floating-point numbers should contain a decimal point or an exponent, which may begin with either e or E. A floating-point number may also have a + or - sign. So 0.0, -1.4e12, and 3.14159 are all valid floating-point numbers. The range of valid floats is again implementation-dependent, but you should expect that any valid, short, floating-point number, as defined by the IEEE standard, is acceptable. (The IEEE is the Institute of Electrical and Electronics Engineers, a professional and standards-making organization.)

Note that the original LiveScript language, as well as early versions of JavaScript for Netscape, attempted to treat all the numeric types the same. Because it has become JScript, there has been a convergence toward the numerical types of the Java language, and the distinction between integer values, such as 5, and floating-point (or real) values, such as 3.3333, has increased.

Caution
LiveScript is now completely obsolete. It has been replaced by its descendants, JavaScript, and JScript. Avoid any code you encounter that is labeled as LiveScript, as it will almost certainly not work correctly.

Note
Watch out for changes in the way JScript handles numeric types. In the future, the distinction between integers, single-precision floating-point types (floats), and double-precision floating-point types (doubles) may become much sharper.

Strings. In JScript, strings may be specified using either single quotes ('stuff') or double quotes ("otherstuff"). If you begin a string with one type of quote, you must end it with that same form of quote-for example, "badstuff' is not a legal string in JScript. Strings may also be nested by alternating the types of quotes used. In fact, you must alternate single and double quotes if you wish to put one string inside another. Here is an example of several nested strings:

"Oh, it's 'Tommy this' and 'Tommy that' and 'throw 'im out, the brute'."

As in C and Java, JScript strings may contain special combinations of characters, known as escape sequences, to denote certain special characters. The rules for this are still emerging, but it is probably safe to assume that all the escape sequences defined in C will be supported. Because you will almost always be using formatting directives of HTML (such as <BR> for a line break) you will probably not use these directives very often. At the moment, the following sequences are supported:
\t
tab
\r
line feed
\n
return
\f
form feed (vertical tab)
\b
backspace

See the "Manipulating Text Fields" section of Chapter 6 "Interactive HTML Objects," for more information on combining HTML directives with text.

The special string "" or '' represents the zero-length string. This is a perfectly valid string whose length is zero. This is the shortest JScript string; the length of the longest is, as usual, implementation-dependent. It is reasonable to expect that most JScript environments will permit very long poems (or very short legislative measures) to be represented as single strings.

Logical Values. The logical, or Boolean, values true and false are typically used in expressions that test some condition to determine how to proceed. If that condition is met, one set of statements is executed; if it is not, another set is used instead. The first corresponds to the true condition, whereas the second represents the false condition. Not surprisingly, such expressions are known as conditional expressions. As you will see in the following section on "Operators," there are several comparison operators, such as the equality test (==), which result in logical values.

It is possible to think of true as 1 and false as 0. In fact, JScript often converts these logical values into 1 and 0, respectively. JScript also accepts any non-zero integer in place of true, for example, so that 5 and -3 can both be used as stand-ins for true. Many different programming languages follow this same convention. It should be avoided in JScript, as it can lead to type confusion.

The Value null. The value null has a very special role in the JScript language. It is the value of last resort, so to speak, for every variable. For the beginning JScript programmer, its primary role will be in initializing variables that do not have any more meaningful initial value. For example, in the set of variable declarations given in the preceding section on "Variables and Values," to initialize y to some value, we should have actually written:

var y = null

This prevents JScript errors that arise when an uninitialized variable is accidentally used in an expression that requires a value. It is important to realize that the value null does not give the variable y any implicit data type. null also has the property that it may be converted to a benign form of all the other types. When it is converted to a number, it becomes 0; when it is converted to a string, it becomes the empty string ""; and when it is converted to a Boolean value, it becomes false. This is the one case where it is permissible to change the implicit data type of a variable after it is declared.

Therefore, statements such as:

var lk2 = lk + y
var w = x + y

result in lk2 having the value "lucky" (the same as lk) and w having the value 10 (the same as x). This is why the value null is an excellent way of initializing variables-it is guaranteed to be harmless.

Type Conversion

Several of the examples in the previous section use the + operator to combine different types of things. You may recall that when a string is combined with a number in the form:

stringthing + numberthing

the number is converted to a string and the + operator then glues the two strings together (known as concatenation). However, if they are combined in the opposite order:

numberthing + stringthing

then JScript attempts to convert the stringthing to a number and add it, numerically, to numberthing. If the stringthing can be converted to a string, such as "-14," then all goes well; if it cannot, an error results. This illustrates the concept of implicit conversion in JScript.

We have already seen that some examples of implicit conversion are completely safe. false can be converted to 0, "5" can be converted to 5, and null can be converted to just about anything. However, some conversions are obviously invalid, and others might be questionable. Questions such as: "May the string '3.0' be legitimately converted to the integer 3?" are actually very difficult to answer with complete generality.

There are two approaches to handling this complex issue: Use explicit conversion whenever possible, and use implicit conversion with great care. A detailed study of explicit conversion is in Chapter 5, "Built-In JScript Objects," beginning with the section, "The String Object." For the moment, we will use the following rules of thumb.

See the "The String Object" section of Chapter 5 "Built-In JScript Objects," which discusses the rules for string-to-number and number-to-string conversion, the source of most conversion errors in JScript.

Caution
Use implicit conversion only when converting to a string form. Never use it to convert to numerical form. This is because attempts to convert a non-numerical quantity to a numeric form cause serious JScript errors, while conversion to string form generally do not.

You have probably already noticed that conversion to a string is always safe, at least for the data types we have encountered so far. In fact, this type of implicit conversion is a boon to the JScript programmer, since it avoids the tedious formatting directives that are necessary in many languages such as C. In JScript, we can say:

"This page has been accessed " + cnt + " times today"

without having to worry about the data type of the variable cnt. This construction will always give a valid string, and never an error.

The preceding Caution is also based on standard principles of defensive programming. There are many things that cannot be sensibly converted to a numerical form, so the prudent approach is never to try to implicitly convert anything to a number. There are several more robust approaches that can be used in case we have a string that we want to convert to numerical form. These are described in Chapter 5. We will also see other exceptions to this rule as our mastery of JScript deepens.

Statements and Operators

The basic unit of work in JScript is the statement, as is the case in most programming languages. A JScript statement accomplishes work by causing something to be evaluated. This can be the result of giving a value to a variable, by calling a function, by performing some sort of calculation, or any combination of these. We have already seen variable declaration statements, which not only create (declare) a new variable, but also give it an initial value, such as the following statement:

var x = 10

JScript programs, as mentioned at the beginning of this chapter, are collections of statements, typically organized into functions, which manipulate variables and the HTML environment in which the script itself works, in order to achieve some goal.

The Structure of JScript Statements

Before plunging into a detailed description of the various types of statements and the operators they use, let's examine one simple statement in excruciating detail. Consider the statement:

y = x + 5

This statement contains three parts: the result y, the operator =, and the expression x + 5. The result always occurs on the left side, because JScript always operates from left to right, and is often called the lvalue. The result must always be something that can be modified. It would be erroneous to write null = x + 5, for example, because null is a built-in, unchangeable component of JScript itself-it cannot be modified, so it can never appear as a result.

The operator = is the assignment operator, of course. It causes the expression on the right to be evaluated and its value given (assigned) to the result. The expression x + 5 contains another operator, the + operator, which acts to combine x and 5 in some context-specific way. Since x is a number in this case, the + operator performs ordinary addition, and y gets the value 15. As we have already seen, if x had been a string, such as "bleh," then + would have acted as a string concatenation operator and y would be given the value "bleh5" instead. This is an example of operator overloading-the + operator can do different things in different situations. Several JScript operators are overloaded.

There is one final point to be made about this statement, and about the structure of JScript programs in general. JScript has adopted a line-oriented approach to program flow. This means that it knows that a statement has ended when it reaches the end of a line. It is also possible to explicitly terminate a statement with a semicolon character (;). The statement y = x + 5; is identical in effect to the statement y = x + 5. This also means that you can, in fact, put multiple statements on a single line by separating each of them with a semicolon.

For those just starting out in JScript, it is often a good idea to terminate each statement with a semicolon, and also to put only a single statement on each line. This might seem both redundant and extraneous, but it is well justified. The end of a line is often a purely visual concept. Anyone who has ever used a word processor has undoubtedly encountered the situation where a very long line looks like two lines. Different platforms (PC, Macintosh, UNIX) also have their own unique ideas as to what the proper end-of-line characters are. It is much safer to put in the extra semicolon character and be explicit about the end of the statement than it is to rely on one's eyesight.

Operators

The set of operators that JScript uses is, once again, very similar to that of the C, C++, and Java languages. It provides a number of different ways of combining different values, both literals and variables, into expressions. Some operators require two elements to participate in the operation, and are referred to as binary operators. The + operator is a binary operator. Other operators require only a single participant (operand), and are known as unary operators. The ++ operator, which adds 1 to its operand, is a unary operator. Operators may also join forces to form aggregate operators, as we shall see next.

JScript operators may be classified into the following groups:

This grouping is purely functional, and is based on what the operators actually do. The next four subsections examine each type of operator in more detail. Table 2.1 summarizes the operators in each category and how they are used.

Table 2.1   A Summary of JScript Operations

Symbol
Computational Operators
+
Addition, String Concatenation
-
Subtraction, Unary Negation
*
Multiplication
/
Division
%
Modulus
++
Preincrement, Postincrement
--
Predecrement, Postdecrement
 
Logical Operators
==, !=
Equality, Inequality
<,<=,=>,>
Arithmetic and String Comparison
!
Logical NOT
&&,||
Logical AND, Logical OR
?
Conditional Selection (trinary)
,
Logical Concatenation
 
Bitwise Operators
&,|
Bitwise AND, Bitwise OR
^
Bitwise exclusive OR (XOR)
~
Bitwise NOT
<<,>>,>>>
Shift Left, Shift Right, Unsigned Shift Right
 
Assignment Operators
=
Assignment
OP=
Aggregate Assignment (+,-,*,/,%,&,|,^,~,<<,>>,>>>)

Computational Operators. The computational operators are addition (+), subtraction and negation (-), division (/), multiplication (*), modulus (%), increment (++), and decrement (--). These operators are often used in performing arithmetic computations, but do not forget that the + operator is overloaded; it also has the extremely important role of string concatenation.

The first five computational operators have their standard mathematical meanings. They add, subtract, divide, or multiply two numeric quantities. By combining two quantities using one of these operators, the result is made as precise as possible. If an integer is added to a floating-point number, the result is a floating-point number. The following four statements illustrate the use of these operators:

x = 4 + y;
y = 5.5 - z;
z = 10 / w;
w = 1.4e5 * v;

Note that division of integer quantities returns a result which is as precise as possible, so that if w had the value 4 in the third statement, z would get the floating point value 2.5, not the integer value 2. Note also that the - operator may also be used as a unary operator to compute the negative of a numeric quantity:

n = -m;

This has exactly the same effect as if we had multiplied m by -1.

The modulus operator (%) is used to compute the remainder from a division. Although it can be used with floating-point numbers, it is typically used with integers, so that 21 % 4 evaluates to 1. The modulus operator always gives a remainder that has the same sign as the corresponding quotient, so that -21 % 4 evaluates to -1, not 3.

The increment and decrement operators are conveniences created to simplify the very common operations of adding or subtracting one from a number. Both these operators are unary and come in two forms: prefix and postfix. The expression ++x is the preincrement form of the ++ operator, while x++ is the postincrement form. This leads to a subtle and often misunderstood point about the increment and decrement operators.

Supposing that x has its usual value 10, consider the two statements:

y = ++x;
z = x++;

These look very similar, but are in fact very different. After both of these statements have been executed, x has the value 11. However, y ends up with the value 11, while z has the value 10. Why? The reason has to do with the complex issue of in what order the operators ++ and = are evaluated in these two statements. In the first statement, the ++ is evaluated first, so that x attains the value 11, and then the assignment = is evaluated, so that this value is passed on to y. In the second statement, the assignment operator = is applied first, so that z becomes 10, the current value of x, and then the ++ is applied to x, so that it advances to 11. The same rule applies to the decrement operator (--).

This might seem like it is a violation of the rule of left-to-right evaluation, and it is. Even though the equals sign is to the left of the preincrement operator (++) in the first statement, the ++ operator takes effect first. This is an example of operator precedence, the order in which multiple operators are applied. This complex topic is discussed in more detail in the "Order of Evaluation" section later in the chapter.

Note
Internet Explorer 3.0 has a bug in its order of evaluation. The right side of an expression is always evaluated completely before the assignment takes place. In IE3.0, both y and z will have the value 11.

Logical Operators. Logical operators in JScript are used either to carry out some form of test, or to combine the results of more than one such test. They are often referred to as conditional operators. The logical operators that perform a test of some sort are the equality/inequality operator (== and !=), the comparison operators (<, <=, >, and =>), and the logical negation operator (!). The operators that combine logical values are logical AND (&&) and logical OR (||). Finally, the conditional operator (?) and the comma operator (,) are also combining operators, although they are only vaguely logical operators.

Equality Operators. The binary equality (==) and inequality (!=) operators are used to test if two quantities are the same or different. These operators are overloaded. On integers, they test for strict equality or inequality. On floating-point numbers, they test to see whether the two quantities are equal within the precision of the underlying floating-point type. On strings, they test for exact equality-recall that case is significant in JScript strings. These operators all return a Boolean value, either true or false.

For example, if x has the value 10, y has the value 3.0, and z has the value "barney," then x == 10 is true, y != -5.0 is also true, and z == "fred" is false. Unfortunately, even operators as simple as these can be a source of error. It is regrettable that the logical operator == looks so much like the assignment operator =. Consider the following incorrect code fragment:

if ( x = 3 ) {
     stuff...

The purpose of this code is almost certainly to test the value of the variable x against the constant 3, and to execute the "stuff" if that test succeeded. This code fails to realize that purpose in two very dramatic ways, just by inappropriately using = instead of ==.

First of all, x = 3 always gives x the value 3, no matter what its previous value was. Instead of testing x using ==, we have altered it with =. Second, the value of the expression x = 3 is the value of its left side, namely 3. Even though 3 is not a true logical value, it is treated as true by the if statement (if is described in greater detail in the section "Control Structures" later in this chapter). This means that "stuff" will always be executed, rather than being executed only when x has the prior value 3.

This type of error occurs in every programming language in which similar operators are used for very different purposes. In this case, we could have adopted another rule of defensive programming and said:

if ( 3 = x ) {
     stuff...

In this case, our typing mistake (= instead of ==) leads to an error, rather than resulting in a subtle programming flaw. Since 3 is a constant, it can never appear on the left side of an assignment, but it is quite capable of appearing on the left side of a logical test. Said another way, since x == 3 and 3 == x are completely equivalent, the form 3 == x is preferable. If it is mistyped as an assignment statement (3 = x), it leads to an immediate error, rather than one that might take hours of debugging to uncover. This leads to the following advice.

Tip
When testing for equality, always put constants on the left, especially null.

There is another subtle evil about the (in)equality operators when they are used with floating-point numbers. It is very tricky to make floating-point arithmetic completely independent of the underlying machine. This means that z == 3.0 might be true on one machine but false on another. It can also lead to seemingly absurd results such as 3. == 3.00 being false while 3.0 == 2.9999999 is true. A remedy for this problem is presented at the end of this section.

Comparison Operators. The comparison operators (<, <=, >, and >=) also operate on both numbers and strings. When they act on numbers, they perform the usual arithmetic comparisons, yielding Boolean values, as with the equality operators. When they act on strings, they perform comparisons based on dictionary order, also known as lexicographic order. If a string str1 occurs earlier in the dictionary than a second string str2, then the comparison str1 < str2 (and also str1 <= str2 ) will be true. For example, "barney" < "fred" is true, while "Franklin" < "Delano" is false.

The Negation Operator. The logical negation operator (!) is used to reverse the sense of a logical test. It converts true to false and false to true. If x < 15 is true then !(x < 15) is false, and vice versa. Note that ! may also be used with integer values, so that !0 is true, while !5 is false. As in other cases, this use of the ! operator violates type boundaries and should be avoided.

Boolean Logical Operators. The logical AND (&&) and OR (||) operators are among the most powerful operators in JScript. Both may be used to combine two or more conditions into a composite test. The logical AND of a set of conditions is true only if all of its component conditions are true. The logical OR of a set of conditions is true if any of its component conditions are true. Thus:

( x < 17 ) && buttonPressed && ( z == "Meta" )

is true precisely when x is less than 17 and the Boolean variable buttonPressed is true and z is exactly equal to the string "Meta." Similarly,

( x < 17 ) || buttonPressed || ( z == "Meta" )

is true if one or more of the three conditions is true.

Lazy Evaluation. JScript uses a lazy variant of its usual left-to-right evaluation rule with the && and || operators. This lazy evaluation (or short-circuit evaluation) rule states that JScript stops trying to evaluate the expression as soon as its value is known.

To see how this works, suppose that x has the value 20, buttonPressed is true, and z is the string "Hyper". Because ( x < 17 ) is false, the second and third conditions in the logical AND statement are never evaluated. This is because false && anything is always false, so the value of the first expression must be false. Similarly, the second statement stops as soon as buttonPressed is evaluated. Since true || anything is always true, the second expression must be true.

Lazy evaluation can be both a boon and a curse. Suppose that "digofpi(1000000000)" is a function that computes the billionth digit of pi. The expression:

( x < 25 ) || ( digofpi(1000000000) == 3 )

does not actually try to compute the billionth digit of pi if x is 20, because the expression is already known to be true, and digofpi() is never called. As an additional example, consider the following expression:

( x < 25 ) && beaupage()

Suppose that beaupage() is a function that displays a beautiful Web page. If x is 30, this page will never be seen, because the first part of expression ( x < 25 ) is already known to be false. As a result, the function beaupage() is never called. We revisit this phenomenon in the "Functions and Objects" section at the end of this chapter. For the moment, it is wise to be aware of lazy evaluation.

Fuzzy Comparison. The logical AND and OR operators also provide us with one solution to the problem of floating-point comparison. While it may not be possible ever to determine whether x is exactly equal to the constant 3.0, you can be certain that it is close using a combined test such as:

( x - 3.0 ) < epsilon || ( 3.0 - x ) < epsilon

where epsilon is some suitably small value, such as 0.001. This form of test is often referred to as a fuzzy comparison.

Caution
Floating-point arithmetic is not an exact science. Avoid exact comparison tests such as == and !=; use fuzzy comparisons instead.

The Comma and Question Mark Operators. The final two operators in the logical category are the conditional operator (?), often called the question mark operator, and the comma operator (,). These two operators are only vaguely logical, but they don't readily fall into any of the other categories either.

The conditional operator is the only trinary (3-operand) operator in JScript. It is used to select one of two possible alternatives based on a conditional test. The syntax for this operator is:

( conditionthing ? truealt : falsealt )

If the conditionthing is true, the value of this expression is truealt; otherwise, it is falsealt. Note that the colon (:) separating the true alternative from the false alternative is mandatory. This can be used to select an appropriate alternative and simplify code, as in this example:

printme = ( errorcode == 0 ? "OK" : "error" );

This expression makes the variable printme have the string value "OK" in case the variable errorcode is 0; otherwise, it is set to "error". The question mark operator is often a fast way to select one of two choices when a control structure would be unnecessarily cumbersome.

Finally, the lowly comma operator can be used to force the evaluation of a set of expressions. All intermediate results are discarded, and the value of the very last expression on the right is returned. For example, the expression:

b = (d = digofpi(1000000000)), beaupage(), (x < 17);

always computes the billionth digit of pi and assigns it to the variable d, always displays the beautiful page, always compares x against 17, and returns only the result of that comparison since x < 17 is the rightmost expression. The result of that comparison is assigned to the Boolean variable b. This might seem like a clever way to outwit JScript's lazy evaluation, but it would be clearer simply to write:

d = digofpi(1000000000);
beaupage();
b = ( x < 17 );

In general, the comma operator is useful only when it is inside a for loop (see "Control Structures," later in this chapter), and should otherwise be ignored.

Bitwise Operators. In many situations, you do not need to know, nor do you want to know, the precise binary representation of values in your program. There are some situations, however, in which it is absolutely essential to operate at the lowest possible level and deal with the individual bits of a particular value. This often arises in mathematical applications, for example, or when precisely manipulating color values. The bitwise operators are used for this purpose. Table 2.2 shows JScript's bitwise operators. Note that all are binary, except for bitwise not, which is unary. Each operates on its operands one bit at a time.

Table 2.2  JScript's Bitwise Operators

Operator Name
Symbol
Bitwise AND
&
Bitwise OR
|
Bitwise XOR
^
Bitwise Left Shift
<<
Bitwise Signed Right Shift
>>
Bitwise Unsigned Right Shift
>>>
Bitwise NOT
~

Bitwise AND (&) examines each bit position in each of its operands. If both operands have a 1 bit in a given position, then that bit will also be set to 1 in the result. In all other cases, the output bit position is zero. For example, suppose x = 0x00001234 and y = 0x8000ABCD. Then z = x & y will have the value 0x00000204. You can see this more easily by writing x and y in base 2 (binary) notation, and looking for those positions in which both x and y are 1, as shown in the first part of Figure 2.1.

Figure 2.1 : JScript's bitwise operators operate on each bit separately.

Note that x and y have only the same bits set in highlighted positions, so that those are the only bits set in their logical AND z. In this way, bitwise AND is the bit level analog of the logical AND. Bitwise OR (|) is similar. If either bit is 1 in any bit position, then that bit will be 1 in the result. Thus, the value of w = x | y will be 0x8000BBFD, as you see in the middle part of Figure 2.1.

Each bit is set in w if either or both of the corresponding bits in x and y is set. The bitwise XOR (exclusive OR) (^) operator is a variation on the bitwise OR operator. It sets a bit in the result if either bit in the operand is set, but not both. The value of v = x ^ y is 0x8000B9F9, as shown at the bottom of Figure 2.1.

These three operators may also take more than two operands, so that it is possible to write a very long expression such as:

n = ( a & b & c & d & e );

which operates from left to right, as usual. This expression takes the bitwise AND of a and b, ANDs that result with c, ANDs that result with d, and finally ANDs that result with e. The final result is saved in the variable n.

Caution
The bitwise AND (&) and OR (|) operators bear a shocking similarity to their logical counterparts && and ||. This can lead to painfully undetectable errors. The same care that is exercised with = and == should also be used with these operators.

The unary bitwise NOT operator (~) changes each 0 bit in its operand to a 1 bit, and each 1 bit in its operand to a 0 bit. The bitwise NOT of x will have the value 0xFFFFEDCB:

x 0000 0000 0000 0000 0001 0010 0011 0100
~x 1111 1111 1111 1111 1110 1101 1100 1011

While &, |, ^, and ~ operate on bits in place, the shift operators <<, >>, and >>> are used to move bits around. The left shift operator (<<) shifts a set of bits to the left by a specified number of positions, while both >> and >>> move that set of bits to the right in two potentially different ways. For example, let us evaluate these three expressions:

xleft = x << 5;
ysright = y >> 3;
yusright = y >>> 3;

The first of these shifts each bit in x to the left by five positions. Zero bits are tacked on at the right, while the bits that are shifted out at the left are lost when they exceed the overall 32-bit length. So the value of xleft must be 0x00024680. The signed right shift operator acts in almost the same way. Each bit of y is shifted to the right by three positions. Bits on the right edge of y are lost as they are shifted out. However, rather than shifting in zeroes at the left side of y, the most significant bit of y, which happens to be 1 in this case, is shifted in. The resulting value of ysright is 0xF0001579.

This might seem counterintuitive, but it makes good mathematical sense, since it preserves the sign of the operand. If y is negative (most significant bit set, as in our example) then any signed right shifted version of y will also be negative. Similarly, if y had been positive (most significant bit equal to 0), then any right-shifted version of y would have been positive. The unsigned right shift operator (>>>) does not preserve the sign of its operand; it always shifts 0 bits in at the left edge. The value of yusright is therefore 0x10001579. The shift processes used to compute xleft, ysright, and yusright are shown in Figure 2.2.

Figure 2.2 : JScript's shift operators move bits to the right or left, and are equivalent to multiplication or division by a power of two.

Since all the bitwise operators act at the bit level, chaos can result if they are applied to a variable that is not an integer. Floating-point numbers are particularly sensitive, since an arbitrary bit pattern need not correspond to a valid floating-point number.

Caution
Never perform bitwise operations on floating-point numbers. Your code will be unportable, and floating-point exceptions may result.

Assignment and Aggregate Operators. Our tour of JScript operators concludes with the assignment operator and its aggregates. You have already seen many examples of that most fundamental of all operators, the assignment operator (=). You are well aware that it is used to assign the result of an expression or value on the right side of the = sign to the variable or lvalue on the left side of the = sign.

In JScript, as in C, C++, and Java, you can also combine the assignment operator with any of the binary computational and logical operators. The expression:

Left OP= Right ;

is just a shorthand for the expression:

Left = Left OP Right ;

where OP is any of the operators +, -, /, *, %, &, |, ^, <<, >>, or >>>. So to add 7 to x, multiply y by 19.5, OR z with 0xAA7700, and perform an unsigned right shift of 10 bits on w, you can write:

x += 7;
y *= 19.5;
z |= 0xAA7700;
w >>>= 10;

These compact expressions replace the wordier versions x = x + 7; y = y * 19.5, and so forth.

Order of Evaluation. In elementary school math, you were probably confronted with questions such as, "What is the value of 3 + 4 * 5? Is it 23 or is it 35?" This was your first exposure to the concept of order of evaluation, or operator precedence. You probably remember that multiplication has a higher precedence than addition, so that the correct answer is 23. The same issue arises in almost every programming language with the concept of operators-which comes first?

There are two approaches to this issue. The first involves learning, or attempting to learn, the operator precedence table. The more operators there are, the more rules there must be in this table. The second approach is to simply ignore the issue completely and explicitly group your expressions using parentheses. Never write 3 + 4 * 5. Always write 3 + ( 4 * 5 ) or even ( 3 + 4 ) * 5, if that is what you want.

This recommendation is very much like several others in this chapter. It trades the effort (and perhaps some readability) of using the explicit parenthesized form against the promise that the order of evaluation will always be exactly as you wrote it. Incorrect order of evaluation is almost certainly the second most common source of programming error in JScript (confusing = and == is the first). For the daring, Figure 2.3 shows the operator precedence table for JScript. For everyone else, the following tip contains the recommended rule of thumb.

Figure 2.3 : Use the operator precedence table to determine the order of evaluation.

Tip
Use parentheses to explicitly specify the order of evaluation in expressions containing more than one operator.

There is one case in which no amount of parentheses will help. When using the increment (++) and decrement (--) unary operators, you must simply know that preincrements and predecrements always happen before anything else.

Comments in JScript Code

All professional code should have comments that clearly indicate the purpose and logic behind each major section of the code. JScript offers two comment styles-the original comment style from C and the single line comment style from C++ and Java.

C style comments are typically used to document major functions or code blocks. Because a C comment may extend over multiple lines, it is ideal for detailed discussions of important parts of the code. A C comment begins with /* and ends with */. Our aesthetically pleasing function beaupage() might begin with a thorough description of just what makes it so beautiful, as follows:

/*
  The function beaupage() draws a stunningly beautiful
  Web page by performing the following nineteen steps.
  ... list of the 19 steps
*/

By contrast, C++ style comments are most suitable for short, pithy descriptions which will fit on a single line. A C++ style comment begins with // and ends at the end of the current line. Critical variables, for example, might merit a C++ style comment indicating how they will be used, as follows:

var done = false; // set to true when we are all done

Both comment styles may be mixed freely in the same JScript program. However, such comments should never be nested, as this can lead to confusion. Also, the temptation to use HTML style comments (<!-- and -->) should be strongly resisted, for reasons which will become clear in the next chapter.

See the section, "The <SCRIPT> Tag," of Chapter 3 "Events and JScript," for more information on the relationship between HTML comments and JScript.

Troubleshooting
I have just written my first JScript program. Everything looks just fine, but the code does nothing. What is wrong? Here is the code:
/* My first JScript program *?
...many lines of code not shown
/* End of my first JScript program */
Your comments are well thought out and informative. Unfortunately, your very first comment begins with /* but does not end with */. You have inadvertently typed *? instead of */, so that the comment does not end until very far down in your program. When you use C-style comments, always make sure that they match.

Control Structures

At this point, you have had just enough of the JScript language to declare variables, perform assignments, and do various types of arithmetic, string, and logical calculations. You are not yet able to write any meaningful code, because you do not have any higher-level constructions. In this section, we will consider various methods of controlling the way in which statements are executed. The next section will expose the highest level of JScript-its functions and objects.

There are three types of control structure in JScript, as follows:

These three control structures are very similar. Each is introduced by a keyword (while, for, and if, respectively) and each manipulates a block of JScript statements. A block is introduced by a left brace ({) and terminated with a right brace (}). There can be as many JScript statements between { and } as you want, or as few. A block of code can even be empty, with nothing between the braces. In many ways, a block of statements is like a single gigantic statement. In particular, block-structured constructs are often all or nothing-either the entire contents of the block are executed, or none of it is. Since blocks behave like single statements, it is also possible to put blocks inside other blocks, in a nested fashion.

As you will see, each of the three control structures has its own specific format and its own special uses, although it is often possible to achieve the same results using any of the three types, with varying degrees of elegance.

The if Statement

The if statement is used to conditionally execute a single block of code. It has two forms, the simple if statement and the if...else statement. The simple if statement consists of a conditional expression, known as the if test, and a block of code which is executed if that expression evaluates to a Boolean true. An example of an if statement follows:

if ( condstmt ) {
     zero or more statements
     }

The block of code within the braces is often called the if block. The conditional statement condstmt can be any expression that yields a logical value. Note that numerical expressions may also be used; 0 is construed as false, and all other values are taken to 5be true. As stated earlier, an if statement should be considered a single statement. Code blocks are not traditionally terminated with a semicolon, although there is no harm in doing so. Listing 2.1 shows an example of a simple if statement.


Listing 2.1  The if Control Structure
if ( ( x < 10 ) && ( -10 < x ) ) {             // if test
     y = ( x * x * x );                        // 1: cube of x
     ystr = "The cube of " + x + " is " + y;   // 2: informative string
}

In this example, the value of x is tested to see whether it is less than 10 and also greater than -10. If the result of this test is true, then the variable y is set equal to the expression x * x * x, known mathematically as the cube of x, in the statement 1 (labeled 1:). The variable ystr is then set to a string that expresses this cubic relationship between x and y, in statement 2. If x fails either of the two tests in the if test, neither of the two statements in the if block is executed.

It is easy to see even in this simple example that it is often desirable to have a contingency plan in case the if test is false. This leads to the second form of the if statement, the if...else control structure. In this form, one block of code is executed if the if test passes, and a second block is executed if it fails. The format of this type of if statement is as follows:

if ( condstmt ) {
     ifblock of statements
} else {
     elseblock of statements
}

Note
In the current version of JScript, the placement of the braces is not important. The opening brace ({) may be on the same line as the if keyword or on the line immediately following it. Earlier versions, such as the JavaScript release bundled with Netscape Navigator 2.0, enforced much stricter rules on where { and } could be put.

In this form of the if statement, the if block is still executed if condstmt is true. However, in this case, the block of code following the else is executed if condstmt is false. Listing 2.2 shows an enhanced version of the code from Listing 2.1 using the if...else form.


Listing 2.2  The if...else Control Structure
if ( ( x < 10 ) && ( -10 < x ) ) {                // if test
     y = ( x * x * x );                           // 1: cube of x
     ystr = "The cube of " + x + " is " + y;      // 2: informative string
} else {                                          // false case
     y = null;                                    // 3: be paranoid; give y a Âvalue
     ystr = "Cannot compute the cube of " + x;    // 4: explain the failure
}

In this example, statements 1 and 2 are still executed if x meets both tests in the if test. If either test fails, statements 3 and 4 in the else block are executed instead. Statement 3 is another example of defensive programming. The variable y is given a value, albeit a meaningless value. This is done so that if y is used later, it will be guaranteed to have some value (even if we forgot to initialize it) regardless of whether the code flowed through the true part of the if (the if block) or the false part of the if (the else block).

Observe that ystr also gets a value no matter which of the two blocks is used. In the true case, it has the informative string documenting the cube of x; in the false case, it has a string indicating that the cube of x could not be computed. Because ystr will presumably be displayed to the user at some point, it is worthwhile to provide an error message. This is an example of parallel code design. Each conditional path modifies the same set of variables. For a simple case, such as Listing 2.2, it is easy to ensure that this happens. There are only two variables, y and ystr, and we can see exactly where they are set in every case. For more complicated, nested conditional expressions, it can become almost impossible to observe every variable in every case. Parallel code design is a good goal to strive for nonetheless.

The while Statement

The while statement is used to execute a block of code while a certain condition is true. The format of the while statement is as follows:

while ( condstmt ) {
     zero of more statements
     }

The condition clause condstmt is evaluated as a logical expression. If it is true, the block of statements between the braces is executed. The flow of control then loops back to the top of the while statement, and condstmt is evaluated again. This process continues until the condstmt becomes false, or until some statement within the block forces it to terminate. Each pass through the block of code is called an iteration. Figure 2.4 illustrates the basic structure of a while statement.

Figure 2.4 : JScript's while control structure executes a block of statements conditionally.

The first fundamental difference between a while statement and an if statement is that the while block may be executed many times, while the if or else blocks are executed once at most. You might well wonder how a while statement ever terminates. The code shown in Listing 2.3 illustrates a simple situation in which the while block eventually leads to the condstmt becoming false.


Listing 2.3  A while Loop which Adds a Sequence of Numbers
var x = 1;
var xsum = 0;

while ( x <= 10 ) {           // loop until x is greater than 10
     xsum += x;               // add x to the running sum xsum
     x++;                     // increment x
}

This code accumulates the sum of all the integers between 1 and 10, inclusive, in a variable called xsum. x starts out as 1, so that xsum initially becomes 1 as well. x is then incremented to 2 by the x++ statement. That value is then added to xsum, so that it becomes 1 + 2 = 3. This process continues until x finally becomes 11 and the x <= 10 condition is false. xsum at this point has the value 1 + 2 +…+ 9 + 10 = 55. Thus, the loop terminates. Note that it is critically important to initialize xsum to 0. If xsum is not initialized at all, then the statement xsum += x, which is just shorthand for xsum = xsum + x, gives an error. If xsum is initialized to something other than 0, the final result contains that initial value and is not just the sum of the integers from 1 through 10.

Listing 2.3 shows one way in which a while loop can terminate. Statements within the block may cause the conditional statement to become false. It could also happen that the conditional statement at the top of the while was never true, so that the statements within the block are not executed even once. If x had started with the value 20 in this example, the while test would have been immediately false, and the statements xsum += x and x++ would have never been executed. In this event, xsum would retain its initial value of 0.

Using the break Statement. There is a third way for a while loop to terminate. If the special statement break is encountered inside the while block, the loop is forced to terminate immediately. No further statements are executed, and the condstmt is not retested. Execution continues with the first statement after the end of the while block. Listing 2.4 gives an example of the use of the break statement.


Listing 2.4  A while Loop with an Internal break Statement
var x = 1;
var xoddsum = 0;
var xtmp = 0;
var lastx = 0;

while ( true ) {             // 1: loop forever (well, almost)
     xtmp = xoddsum + x;     // 2: compute a trial sum
     if ( xtmp > 100 )       // 3: if it is too large, then...
          break;             // 4: we are done
     xoddsum += x;           // 5: add x to the running sum xoddsum
     x += 2;                 // 6: increment x by 2
}
lastx = x;               // 7: save the final value of x in the variable
 lastx

The test clause of this while (statement 1) is true, which, you might well suspect, is always true. This means that there is no way for this loop to terminate unless it is forced to do so by a break statement. In statement 2, a temporary sum is formed in the variable xtmp. This sum is tested against the limit 100 in statement 3; if xtmp exceeds it, then statement 4, the break statement, is executed, and the loop terminates. If the test fails (xtmp is still less than 100), then the real sum is formed in statement 5. (Note that it would have been equivalent, and slightly more efficient, if we had written statement 5 as xoddsum = xtmp.) In statement 6, x is incremented by 2.

What does this while loop do? It keeps adding up numbers, odd numbers in fact, until the sum is less than 100. When the next sum would have exceeded 100, the if test succeeds, the break is executed, and the flow of control of the program reaches the first statement after the entire while block, namely statement 7. This statement saves the last value of x in a different variable, lastx. This construction computes the largest sequence of odd numbers that can be added without having the sum exceed 100. You can easily determine for yourself that the value of lastx must be 21, since 1 + 3 + … + 21 = 100 exactly, while 1 + 3 + … + 21 + 23 = 123 > 100.

The Perils of Infinite Loops. Listing 2.4 not only illustrates the use of break, it also shows two other elements worth noting. First, Listing 2.4 contains a nested conditional: There is an if statement inside the while block. This sort of construct is extremely common, and many levels of nesting are not at all unusual. Second, this example has another very common but somewhat troublesome feature. Since the while test is always true, there is no way for the while to terminate unless the break statement is executed. In the preceding example, it was quite quickly. Suppose, however, that statement 6 had been incorrectly entered as x -= 2. In this case, xoddsum would be getting constantly smaller and xtmp would never exceed 100. This type of error is known as an infinite loop. Listing 2.3 is not immune either, even though it has a conditional test rather than a blanket true. If the final statement of that example had been mistyped as x--, it would never terminate either.

Naturally, infinite loops must be vigorously avoided. They will terminate only when some kind of internal error happens (such as an arithmetic overflow when something becomes too large) or as a result of user intervention. Unfortunately, there is no foolproof way to write a while statement (or a for statement, as we shall see shortly) that is guaranteed to be correct. JScript is no different from any other programming language in this respect. However, the following general principles will reduce the opportunity for error:

If the while ( true ) construction is used, then the logic that exercises the break statement must be correct. If this logic isn't correct, the loop will never terminate. If you restrict your use of while ( true ), you will have fewer infinite loops. The second suggestion is based on the observation that the more chances there are to exit the loop, the less likely it is that the loop will last forever. Listing 2.5 shows a modified version of Listing 2.4 in which we have moved the test on the sum to the while clause itself, and have also added a very paranoid test on the number of times through the loop (the variable loopcount).


Listing 2.5  An Improved Form of Listing 2.4
var x = 1;
var xoddsum = 0;
var lastx = 0;
var loopcount = 0;

while ( ( xoddsum + x ) < 100 ) {     // 1: loop while sum is < 100
     xoddsum += x;                    // 2: add x to the sum xoddsum
     x += 2;                          // 3: increment x by 2
     if ( ++loopcount > 1000 )        // 4: if we're working too late..
          break;                      // 5: quit
}
lastx = x;                         // 6: save the final value of x in lastx

This version satisfies both rules. Of course, the test in statement 4 is completely unnecessary. The code is simple enough that we can reassure ourselves that it is correct and will not go into an infinite loop. Once you are writing slightly more complicated while loops, you will find that there are usually multiple possible error conditions that arise. Every time you test for an error, you should consider using a break statement.

You will often see while ( true ) written as while ( 1 ). These are equivalent, since true has the numerical value 1, but the latter form is sloppy. The conditional portion of a while, if, or for statement should always be a true logical expression.

Using the continue Statement. There is another special statement that may be used inside while loops: the continue statement. The continue statement is used to force the flow of control back to the top of the while loop. When a continue statement is seen, all statements between it and the end of the while block are skipped, and execution continues at the top of the while. Listing 2.6 shows a simple use for the continue statement.


Listing 2.6  A continue Statement Returns to the Top of a while
var x = 0;
var xsum = 0;
var loopcount = 0;

while ( loopcount++ < 100 ) {   // 1: loop 100 times
     x++;                       // 2: increment x
     if ( ( x % 5 ) == 0 )      // 3: if x is divisible by 5
          continue;             // 4: skip it
     xsum += x;                 // 5: otherwise, add x to xsum
}

This example adds up every number between 1 and 100 that is not divisible by 5. The numbers that are divisible by 5 are skipped by virtue of statements 3 and 4. Statement 3 computes the remainder when x is divided by 5. If that remainder is 0, then x must be evenly divisible by 5. In that case, the conditional in statement 3 is true, and statement 4 is executed. The continue statement causes execution to continue back to the top of the loop at statement 1. This means that statement 5 is not executed, so the sum always misses those values of x which are divisible by 5, and only those values.

Many programmers would write line 3 as if ( ! ( x%5 ) ). While this style is very common, it is also confusing and a potential source of error. One problem with this form is that it confuses JScript types by using the numerical value x%5 as if it were a logical value. This form also hides the explicit test for zero of Listing 2.6. While this ! form is more compact, it is also more error-prone, and should be avoided.

One striking difference between this listing and previous ones is that x is initialized to 0, not 1, and x is incremented at the top of the loop, not at the bottom. If the x++ were at the bottom, what would happen? The values 1, 2, 3, and 4 would all be gleefully added into xsum. When x reached 5, however, statement 3 would be true, the continue in statement 4 would be executed, and both xsum += x and x++ would be skipped. x would stay equal to 5 forever! Since the x++ statement is critical to the correct functioning of the loop, it must occur before the continue. If it occurs after the continue, it will be skipped.

Caution
Any statement that must be executed on every pass through a loop must be placed before any continue statements.

The for Statement

The for statement is the most powerful and complex of the three flow control constructions in JScript. The primary purpose of the for statement is to iterate over a block of statements for some particular range of values. The for statement has the following format:

for ( initstmt; condstmt; updstmt ) {
     forblock
}

The for clause, as shown, has three parts, separated by two mandatory semicolons. The initstmt is typically used to initialize a variable, although any valid statement may be used in this position. The initstmt is always executed exactly once, when the for statement is first encountered. The condstmt is a conditional test, and serves exactly the same function as in the while statement. It is tested at the top of each loop. The for statement terminates when this condition evaluates to false. The updstmt is executed at the bottom of each loop, as if it were placed immediately after the last statement in the for block. It is typically used to update the variable that is initialized by the initstmt.

Listing 2.7 shows a simple example of a for statement. In fact, the code in this listing accomplishes exactly the same task as the code in Listing 2.3. Note that this code does not bother to initialize x when it is declared. This is because the initstmt part of the for loop sets it equal to 1 immediately.


Listing 2.7  Adding Up a Sequence of Numbers Using for
var xsum = 0;
var x;

for ( x = 1; x <= 10; x++ ) {    // 1: loop while x is <= 10
     xsum += x;                  // 2: add x to xsum
}

In many ways, the for statement is very much like a fancy version of the while statement. Many of the observations that were made for while also hold true for the for statement. In particular, it is possible to use the break and continue statements within a for loop. One of the advantages of a for loop is that its update statement is executed on every pass through the loop, even those passes that are cut short by a continue. The continue skips every statement in the block, but it does not cause the update statement to be skipped. The for statement may also be used unwisely, just like the while statement. If the condstmt portion of the for clause is omitted, it is as if a true conditional had been used, so that something within the for block must force looping to terminate. You will occasionally see the construction for(;;), which is identical in meaning to while ( true ). The two semicolons are mandatory.

The for statement also has some unique features that are not shared by while. The first is that variables may actually be declared and initialized within the initstmt portion. In Listing 2.7, we could have dispensed with the external declaration of x and put var x = 1; as the initialization portion of the for loop. This is often very convenient, since the loop variable (x in this case) is often used only within the loop itself, making an external declaration pointless.

Note
If a variable is used only inside a block of statements, it should be declared at the top of that block. This clarifies your code, since it shows which sections of code use which variables (known as variable scope).

A second useful feature of the for statement is that both the initialization portion and the update portion of the for clause may contain multiple statements separated by the comma operator (,). Listing 2.8 shows another version of the code in Listing 2.6, rewritten so that both x and lcnt become loop variables.


Listing 2.8  A for Loop with Multiple Initialization and Update Statements
var xsum = 0;

for ( var x = 1, lcnt = 0; lcnt < 100; x++, lcnt++ ) {
     if ( ( x % 5 ) == 0 )          // if x is divisible by 5
          continue;                 // skip it
     xsum += x;                     // otherwise, add x to xsum
}

This usage underlines the fact that both x and lcnt are used only within the body of the for loop. It is also much more compact than its counterpart in Listing 2.6. In this example, we need not worry about the logical effect of the continue; we know that both x++ and lcnt++ will always be executed. This is also the most common and useful way to use the comma operator.

Finally, there is another form of the for statement that is used exclusively with objects and arrays in JScript: the for...in statement. We will see how this is used in Chapter 4 "JScript Objects." Figure 2.5 shows the basic structure of the for, while, and if statements, and the use of the break and continue statements within them.

See the section, "Objects, Methods, and Properties in JScript," of Chapter 4 "JScript Objects," for a description of the for...in statement.

Figure 2.5 : Control statements determine the flow of execution in JScript.

Caution
The control statements if, for, and while are examples of keywords. Keywords are words which have a special meaning to JScript itself. Keywords may never be used as variable names, so the statement var if = 0; is extremely illegal.

Functions and Objects

The basic statements, expressions, and operators that were discussed at the beginning of this chapter are what computer scientists usually call primitives. Primitives are the building blocks from which more complex elements of a program are constructed. The for, while, and if control structures represent the next higher level of organization in JScript. Each of these control structures deals with blocks of code whose execution is controlled by the various conditional tests and other clauses. The for, while, and if statements are all block-structured.

Functions and objects represent the highest level of organization within the JScript language. We will spend many chapters learning how to make effective use of these concepts. The purpose of this section is to introduce them and describe their basic features.

Functions

A function is a block of code that has a name. Whenever that name is used, the function is called, which means that the code within that function is executed. Functions may also be called with values, known as parameters, which may be used inside the body of the function. Functions serve two purposes. A function is an organizational tool, in the sense that it permits you to perform the same operation without simply copying the same code.

The second purpose of JScript functions is to link actions on a Web page with JScript code. Mouse clicks, button presses, text selections, and other user actions can call JScript functions by including suitable tags in the HTML source for the page.

Event-handler functions are explored in Chapter 3 "Events and JScript," particularly in the "Events and HTML Tags" section.

The syntax for a function statement in JScript is as follows:

function Name ( listofparams ) {
     body
}

The function's Name is given immediately after the function keyword. All function names should be unique, and also should not conflict with any of the statement names which JScript itself uses. You cannot have a function named while, for example, and you should not have two functions both named UserHelp. The listofparams is a comma-separated list of the values that are passed into the function. These are referred to as the function's parameters, or arguments. This list may be empty, indicating that the function does not use any arguments (often called a void function). The function's body is the set of statements that make up the function. Listing 2.9 shows a function that adds up all the integers, starting at 1 and ending at a value given as the sole argument.


Listing 2.9  A Summation function
function summation ( endval ) {

     var thesum = 0;               // this variable will hold the sum

     for ( var iter = 1; iter <= endval; iter++ ) {
          thesum += iter;          // add the integer into the sum
     }                             // end of the for loop
     return( thesum );             // return the sum
}

This function does the same task that came up in the discussions of the while and for statements earlier in this chapter. Now that it has been written as a function, this code never needs to be repeated again. Anytime you want to form the sum 1 + 2 + … + N, you can simply call the function, as summation(N), and it will perform the task. Notice that the endval parameter is used as the argument to the function.

When the function is called, as summation(14) for example, the actual value 14 is used for endval within the function. The function then executes the for statement, with iter <= 14 as its termination condition, adding in each successive value into the variable thesum. When the for loop is done, the function executes the return statement. This causes the function to give the value inside the return statement back to the caller. This means that if we write:

var sum14;
sum14 = summation(14);

the variable sum14 is set to the value returned by the summation function when endval is given the value 14, namely 105. Functions can return any type of value, and are not restricted to returning integers.

There are several things to notice about this example. First of all, the variables thesum and iter, which are declared within the body of this function, are local variables. This means that they are known only within the body of this function, and are therefore completely unknown outside it. It is quite possible, even likely, that there are many functions all of which have a local variable named iter. All these various iters are unrelated. Changing the value of one of these iters would not affect any of the others. This is why the return statement is necessary; it is the only way to communicate the work of the function back to the caller.

This same restriction applies to the parameter endval as well. The arguments to a function may not be changed within that function. We could well have written endval = 15 just before the return statement in Listing 2.9. This statement would do nothing; It certainly would not change the caller's 14 into a 15. It might seem that every function would always have a return statement. This is not the case, however, because it is possible for a function to have side effects without actually returning a value. This happens by referencing external objects, which are our next topic.

Objects

Functions are used to provide a uniform method for organizing code. Objects serve the same purpose for data. Up to this point, the only data items we have seen are simple variables declared with var. Each of these typeless quantities can hold only a single value of some sort at a time. Objects provide the ability to hold multiple values, so that a group of related data elements can be associated with one another.

What JScript calls an object is called a data structure (or class) in many other languages. As with JScript functions, there are two aspects to JScript objects: creating them and using them. For the moment, we will defer the question of how to create objects and concentrate on how they are used. We will also see that a JScript-capable browser will provide a number of its own, built-in objects.

A JScript object is made up of a set of component parts, which are called its properties, or members. Suppose you have an object named appt which you are using to organize your appointments. The appointment object might have properties that specify the date and time of the appointment, as well as the name of the person with whom the appointment will take place. It might also have a general description field to remind you of the purpose of this meeting. Thus, you can imagine that the appt object will have the following properties:

Each of the properties of the appt object is referenced using the dot operator (.). Thus, appt.month refers to the month property and appt.why gives us the reason for the appointment. These references may appear on both the right and left sides of an expression; we may get their values and also set them. Listing 2.10 shows a code fragment that tests the value of appt and displays a message about a current appointment.


Listing 2.10  Using the appt Object
if ( appt.day == Today ) {
     document.write('<BR>You have an appointment today<BR>');
     document.write('See ' + appt.who + ' at ' + appt.time + '<BR>');
     document.write(appt.why + '<BR>');
}

This example assumes that the variable Today has somehow been initialized with today's date, so that the equality test with appt.day is true only for today's appointments. If the test does succeed, then the three statements in the if block are executed. Each of these references document.write. The document object is a built-in object of the browser. This object has a member known as write, which is actually a function. Functional members of JScript objects are known as methods. This particular method takes a string and displays it on the current Web page.

Each of the three strings that are passed to document.write are constructed using + as a string concatenation operator. Each of them references one or more properties of the appt object in order to provide meaningful messages to the user. Each also includes <BR>, the HTML construction for a line break. This ability directly to issue HTML directives is one of the most powerful aspects of JScript, as it allows the programmer dynamically to modify the contents of Web pages using JScript functions and objects.

Once you learn more about the Date object, in "The Date Object" section of Chapter 5 you will be able to construct a much more satisfying version of this example. Even at this stage, however, the advantage of object-based programming should be apparent. Rather than carrying about many variables, you can use objects instead. Each object can contain all the variables of interest to a particular idea. It can also contain method functions that perform related work. Objects can even contain other objects, so that you can organize your data in a hierarchical structure. Subsequent chapters explore these ideas in much greater detail.