- Week 1: Day 3: Functions and Statements
- Predefined Global Functions
- What Is a Statement?
- Control Statements
- Loop Statements
- Summary
- Workshop

## Predefined Global Functions

JavaScript provides many predefined functions. Some of these functions, termed global functions, can be called from any part of a script—just as you can call the functions you have written. However, many predefined functions need to be treated as belonging to objects. This means that they can't be called in the same way that functions have been called so far (as you will learn later in the book). For the moment, let's look at global functions.

**NOTE**

JavaScript's predefined functions use native code (binary computer code) so you can call them but the code they contain cannot actually be seen. They are not written in JavaScript in the way that we write functions.

We have already come across and used some predefined functions such as the
`alert()`, `confirm()`, and `prompt()` functions which
bring up small dialog boxes to enable basic user interaction. These functions
have been around for so long that the majority of browsers support them,
although they are not actually part of core JavaScript. This means that in an
environment other than a Web browser they may or may not be available. For the
moment let's concentrate on the core JavaScript functions.

The predefined core JavaScript functions are listed below.

`decodeURI()`decodeURIComponent()

encodeURI()

encodeURIComponent()

escape()

unescape()

eval()

isFinite()

isNaN()

Number()

parseFloat()

parseInt()

toString()

watch()

unwatch()

With the exception of `watch()` and `unwatch()`, you have
already learned enough to be able to make use of all these functions. The
`watch()` and `unwatch()` functions work with things called
"object properties" to help in debugging. (As object properties are
quite an advanced topic, and we haven't yet covered objects; those
functions will be discussed later in the book.)

All these built-in functions either check or modify data in some way or another. Let's take a look at them now, one by one, and see what they do and how they can make our lives easier.

### URI Encoding and Decoding

*URIs* (Uniform Resource Identifiers) is the most general name for the
addresses used to access files on the Web. A "resource" is a unit of
information that can be addressed. Not only can URIs be used to specify the
address of a Web page, but they also can be used to send it information. You
have probably seen Web sites where the address bar contains a question mark and
lots of `%` symbols that are each followed by two numbers or letters.
These are query strings used by sites, such as search engines, to send data from
you to the server. The reason that much of the data is converted to what is
called *hex form*, also called "escaped form"—when a
character is converted to a `%` and the two characters of its hexadecimal
value—is that some characters such as the space character can't be
carried as they are in a URI.

When a form is used to submit data as a query string using the `HTTP
GET` method, the browser automatically converts the characters that
aren't allowed within a URI to their encoded hex values. To do this using
JavaScript, you need to use built-in functions.

The original JavaScript functions for encoding and decoding URIs were the
`escape()` and `unescape()` functions respectively. Let's
look at an example to clarify just what they do:

var priceRange = "$4 - $6"; var escapedRange = escape(priceRange); alert(escapedRange);

Figure 3.5 shows the output from the code.

**Figure 3.5 Contents of the escapedRange
variable after the escape() function has been applied to the priceRange
variable.**

The `escape()` function has replaced the `$` and space
characters with their escaped values, which are `%24` and `%20`
respectively. The `unescape()` function acts in exactly the opposite way.
When applied to the variable `escapedRange` the `unescape()`
function will turn it back into text again.

Unfortunately the `escape()` and `unescape()` functions encode
characters that do not need to be encoded. They are also slightly inconsistent
from browser to browser in which characters they will encode. To remedy this,
ECMAScript Edition 3 defined four new functions which are intended to replace
the `escape()` and `unescape()` functions. These are the
`encodeURI()`, `decodeURI()`, `encodeURIComponent()`, and
`decodeURIComponent()` functions.

**CAUTION**

`encodeURI()`, `decodeURI()`, `encodeURIComponent()`,
and `decodeURIComponent()` are only supported by Netscape 6+ and Internet
Explorer 5.5+.

The `encodeURI()` function will encode all characters except for
alphanumerical characters and the following characters which it *leaves*
intact:

`! # $ & ' ( ) * + , - . / : ; = ? @ _ ~`

The `encodeURIComponent()` function is slightly different. It will
encode all the characters that the `encodeURI()` function encodes but
will also encode these characters:

# $ & + , / : ; = ? @

Therefore, it only leaves alphanumeric and the following characters intact.

! ' ( ) * - . _ ~

The reason for having two different encoding functions is that sometimes you may want to encode a whole URI including the http:// etc., and at other times you may want to only encode some data to be attached as a query string. Clearly, if you were to encode a complete URI with the encodeURIComponent() function, you would end up encoding the :// part of http:// too. Therefore, two different functions were created: One for thoroughly encoding URI components to be added as a query string; and another function for encoding the address before the query string.

The counterparts of these functions are the `decodeURI()` and
`decodeURIComponent()` functions. The `decodeURIComponent()`
function is similar to the `unescape()` function. It will decode all
encoded characters. The `decodeURI()` function on the other hand will
leave the following characters encoded:

`# $ & + , / : ; = ? @`

### Evaluating Strings as Code

The `eval()` function is unusual in that it takes a string and
processes it as code. Clearly, if this is not to cause an error, the string must
be recognizable as JavaScript. To demonstrate this, try the code in Listing 3.3.

**Listing 3.3** `eval()` Demo (`evalDemo.htm`)

<html> <head> <title>eval() Demo</title> <script language="javascript" type="text/javascript"> <!-- var myCode = "alert('I was a string!')"; //--> </script> </head> <body> <h1>eval() Demo</h1> </body> </html>

In the single line of JavaScript code, a string is stored in the variable
`myCode`. Although you can see it is a piece of JavaScript, JavaScript
itself doesn't realize this. As far as it is concerned, it is just a series
of characters strung together that it has been asked to store in a variable. Now
try adding the following line after the variable declaration:

eval(myCode);

The `eval()` function will force the string to be evaluated as
JavaScript and the alert box should appear.

For the moment we haven't covered enough to make practical use of the
`eval()` function, but take note of it as it comes in very useful as you
will see in later chapters.

### Arithmetic Functions

Often programming is about manipulating numbers. It is no surprise then that JavaScript has a number of built-in functions designed to complement the arithmetic operators you learned about in Chapter 2.

JavaScript provides functions that check whether a piece of data is a number or what type of number it is, as well as functions which enable the manipulation of the numbers.

#### Numerical Checks on Data

There are two conditions that commonly cause arithmetic scripts to fail in
JavaScript. One is that a number is, or becomes, infinite (or too large for
JavaScript to handle, in which case the JavaScript interpreter treats the number
as having the value `Infinity`). The other is that one of the pieces of
data in an arithmetic operation is not a number. To check for these conditions
where they are likely to occur, JavaScript provides two functions:
`isFinite()` and `isNaN()`.

Before examining these functions, it should be mentioned that there are three
special values which have the data type `number`. These are
`Infinity`, `–Infinity`, and `NaN`. `Infinity`
and `–Infinity` represent, respectively, positive and negative
numbers that have become too large for the JavaScript interpreter to handle or
are genuinely infinite. They aren't of much practical use in an operation
except to indicate that a number is too large for the JavaScript interpreter to
reliably process. The other special value `NaN`, which stands for
"**N**ot **a** **N**umber," indicates that an arithmetic
operation could not be carried out:

alert("a" - 10); //alerts NaN

As you already may have guessed, the `isFinite()` function checks to
make sure that a number is not one of the special values `Infinity` or
`–Infinity`. If the number is finite and calculations can be carried
out, then the function returns `true`, otherwise `false`.

It is rare that numbers to be entered directly into JavaScript are too big for it to process. It usually occurs when numbers are raised to excessive powers or divided by zero or a number very close to zero. Special care must be taken when accepting user input that might be used in these ways.

The `isNaN()` function is a little more tricky. It checks that a value
is *not* a number. This allows us to check for numbers without checking for
all of the other four data types in turn. Unfortunately, the function can cause
some confusion at first because it returns `false` if a value is a number
and `true` otherwise (after all it is checking that a value is not a
number). See for example, the following:

alert(isNaN("a")); // alerts true alert(isNaN(2)); // alerts false

If you really want it to return `true` for numbers, the logical NOT
operator can be placed in front of the function thereby reversing the result.

Rather surprisingly `NaN` does not even evaluate as being equivalent
to itself. Therefore:

**CAUTION**

NaN == NaN // evaluates to false NaN === NaN // evaluates to false

To check for the value `NaN`, you must use the function
`isNaN()`:

isNaN(NaN) // evaluates to true

The `isNaN()` function is especially useful when you collect numerical
data from a visitor who is viewing your Web page. If the user enters
non-numerical data either accidentally or intentionally then, without some
appropriate error checking, your script will fail. It is always a good idea to
use the `isNaN()` function to check any data you collect when you process
it in any scripts. Let's look at Listing 3.4, where the
`getModulus()` function we wrote earlier is improved:

**Listing 3.4 **Safely Finding the Modulus (`getModulus.htm`)

<html> <head> <title>Finding the Modulus</title> <script language="javascript" type="text/javascript"> <!-- function getModulus() { var theNum = prompt("Please enter a number", ""); var theModulus = (theNum>=0)? theNum: -theNum; var msg = (isNaN(theModulus))? "Numbers only please.": "The modulus of " + theNum + " is " + theModulus; alert(msg); } //--> </script> </head> <body> <h1>Finding the Modulus</h1> <a href="javascript:getModulus()">Get Modulus</a> </body> </html>

When the link is clicked the function `getModulus()` is called. It
prompts the user for a number and stores the input in the variable called
`theNum`. The conditional operator is used on the following line to try
to find the modulus (or absolute value) of the input. If this input is not
numeric, then the result will be the value `NaN`. On the next line, the
conditional operator is used again. This time the condition is the result from
the function `isNaN()`.

If the result of finding the modulus was `NaN`, then the
`isNaN()` function will return true and the conditional operator will
evaluate to its second operand which is the string `"Numbers only
please."`. Note that the end of this line is a colon and not a
semicolon. A new line for the third operand was started because it is quite
long. If the result of the function was false, then the conditional operator
will evaluate to its third operand, which is an expression. This expression
combines the values of `theNum` and `theModulus`. It generates a
string that tells the user, in a user-friendly way, the modulus of the number
that was entered. Whichever operand the conditional operator evaluates to is
assigned to the variable called `msg`. This message is then alerted to
the user using the code on the final line of the function body.

The `isNaN()` function enabled you to output a result that has some
intelligence to the user. In combination with the powerful control statements
that you will learn about later in the chapter, the `isNaN()` function
can be a very useful tool. Try to get used to using the function to check the
data you collect with HTML forms or prompt boxes when this data should be
numerical. It will help you make more professional scripts and allow you to
avoid a significant number of potential errors.

#### Conversion Between String and Number

There are good reasons for converting strings to numbers and vice versa. For
example, numbers collected from user input are always in the form of a string.
Most times if you perform an arithmetic operation with this data it will
automatically be converted to the `number`` `data type, but
sometimes it is necessary to do it manually. Most notably is when you wish to
add two numbers that are stored as strings. If you try to do this without
converting their data types, then the two strings will simply be concatenated.

Conversely, in other settings, if you do want to concatenate two numbers
which are of the data type `number``,` you will need to convert
their data type to `string` first. If you don't, they will simply be
added.

The `Number()` and `parseFloat()` functions both take a single
argument (or *parameter* if you prefer) and treat it in a very similar way.
If the argument is a number they will return it unaltered, but if it is a string
they will convert its data type to `number` (if possible) so that it can
be used in arithmetic operations. They also both leave the number's
floating point intact (unless all the digits are zeros in which case they are
removed). They differ in two respects: how they treat other data types, and how
they treat strings starting with numerical characters followed by non-numeric
characters.

The `parseFloat()` function will always evaluate to `NaN` if
used on a data type other than `number` or on a string, except when it
contains only arithmetic characters. The `Number()` function, on the
other hand, is a bit more flexible about the data with which it will work. As
you might expect, it will convert `false` and `null` to
`0`, `true` to `1`, and only `undefined` will be
converted to `NaN`. Most of the time your choice of either of these two
functions won't make a difference, but sometimes you may need one effect
rather than the other—depending on how you want the function to treat
non-numeric or string data. As you progress through the book and learn more, you
will become better equipped to make that decision.

If a string starts with numbers and they are followed by other characters,
the `Number()` function will realize it is not a number and return the
value `NaN`. The `parseFloat()` function, on the other hand,
exhibits a special behavior. It removes the non-numeric characters from the end
of the numbers and returns the numeric characters as a number. For example, the
following code shows how the `Number()` and `parseFloat()`
functions handle strings passed to them as arguments:

Number("1.12 is a number"); // returns NaN parseFloat("1.12 is a number"); // returns 1.12

Sometimes you may want to round off a number to get rid of its fractional
part. The `parseInt()` function allows you to do exactly that. It
converts a value's data type to `number` and rounds it down to an
integer in a single step. Here is an example:

parseInt("2.1"); // returns 2 parseInt("2.5"); // returns 2 parseInt("2.99999"); // returns 2

This is useful, but the `parseInt()` function also has another less
well known ability. It can convert numbers with a base between 2 and 36 to a
decimal number (base 10). It does this by taking the number as its first
argument, and then it allows you to specify the number's base as a second
argument. The values can be either the `string` or `number` data
type. For example, see the following:

parseInt("1111", 2); // returns 15

In this case, the number is the value `"1111"`, and the base
was specified as `2`, which is binary. Therefore the first argument is
converted from binary to its decimal equivalent, which is 15. Here are another
few examples:

parseInt(20, 16); // returns 32 parseInt("10", 8); // returns 8 parseInt("30", 4); // returns 12

Note that `parseInt()` still rounds down numbers before
conversion:

parseInt("1111.1111", 2); // still returns 15 parseInt("ff.ffff", 16); // returns 255

The value you give to `parseInt()` must be a string if it is above
base `10`. This is because numbers above base `10` may include
alphabetical characters.

If numerical data is collected from a user and the numbers after the decimal
point are not required, it is a good idea to use the `parseInt()`
function and specify the number's base as 10. This will prevent it being
interpreted as an octal number if the user began the number with a 0. The
`parseInt()` function behaves in the same way as the
`parseFloat()` function if a string starts with a number but continues
with other characters; it will return only the number.

The final function for string-number conversion is the `toString()`
function. It behaves exactly opposite of the `Number()`,
`parseFloat()`, and `parseInt()` functions. Instead of converting
strings containing numeric characters to numbers, it converts numbers to
strings. If you want to add one set of digits to another without them being
summed, it can be done with this function.

The syntax for the `toString()` function is different from that used
for the `Number()`, `parseFloat()`, and `parseInt()`
functions. Instead of taking a value as an argument typed into its parentheses,
it uses something called the dot notation. In this case, the value must be
stored in a data container such as a variable. The variable is then joined to
the function call with a dot. Here is an example:

var myVar = 2; myVar.toString(); // returns the string "2"

The dot tells the JavaScript interpreter to apply the `toString()`
function to the contents of the variable `myVar``,` which causes
its data type to be changed to the data type `string`. You will learn
more about dot notation as it applies to objects and their functions (methods)
later. Let's have a look at the effect this has on a few examples:

var num1 = 12; var num2 = 34; alert(num1 + num2); alert(num1 + num2.toString()); alert(num1.toString() + num2);

As you would expect, the expression on the third line sums the contents of
the two variables `num1` and `num2`. The `toString()` function
causes the next two expressions to behave very differently though. Both functions
would display the following alert box (see Figure
3.6).

**Figure 3.6 After the toString()
function is applied the numbers concatenate!**

The `toString()` function has caused the operands of the `+`
operator to concatenate rather than sum. Remember that in Chapter 2 you learned
that if one of the operands of the `+` sign is a string, then it
concatenates the two operands regardless of the data type of the other.
Therefore there is no need to apply the `toString()` function to both
operands. Applying it to one of them is enough.

It is probably the last thing you would expect, but the `toString()`
function is also able to convert numbers between bases. It does exactly the
opposite of the action taken by the `parseInt()` function. The difference
is that rather than converting a number from a base between 2 and 36 to a
decimal value, the `toString()` function takes decimal numbers and
converts them to a base between 2 and 36. Of course JavaScript only outputs
numbers as decimal values so the "numbers" the `toString()`
function returns aren't of the data type `number`, but rather of the
data type `string`. However, as they look like numbers to all intents and
purposes, this doesn't usually matter.

To use `toString()` in this way, you simply give it the base you want
to convert to as an argument:

var y = 10; y.toString(8); // returns 12 (10 decimal expressed to base 8) var x = 0.5; x.toString(16); // returns 0.8 (0.5 decimal expressed to base 16)

Note that as JavaScript accepts numbers in octal, decimal, or hexadecimal
format, the `toString()` function converts from octal and hexadecimal
numbers to the base you chose as well as from decimal.

By combining the `parseInt()` and `toString()` functions, it is
possible to convert a number from any base between 2 and 36, to any other base
between 2 and 36. As shown below, this can be written into a function so it can
be used multiple times on the same page. Just remember that because the
`parseInt()` function removes floating points the function won't be
accurate with non-integers:

function convertNum(theNum, fromBase, toBase) { var numBase10 = parseInt(theNum, fromBase); alert(numBase10.toString(toBase)); } convertNum(1100, 2, 16);

In this example, the first line takes the 1100 from the argument
`theNum``,` and the argument `fromBase` specifies it as
binary. The `parseInt()` function then converts it to decimal before it
is stored in the variable `numBase10`. On the second line, the decimal
value is converted using the argument `toBase` to specify the base as
hexadecimal. This then alerts the value `c`, which is the hexadecimal
equivalent of the binary value `1100`. Note that the alert could just as
easily be replaced with a `return` keyword for more practical use.