﻿ JavaScript's Primitive Types

JavaScript Debugger     JavaScript Editor ﻿

## JavaScript’s Primitive Types

JavaScript supports five primitive data types: number, string, Boolean, undefined, and null. These types are referred to as primitive types because they are the basic building blocks from which more complex types can be built. Of the five, only number, string, and Boolean are real data types in the sense of actually storing data. Undefined and null are types that arise under special circumstances.

### Numbers

Unlike languages such as C and Java, the number type in JavaScript includes both integer and floating-point values. All numbers are represented in IEEE 754-1985 double-precision floating-point format. This representation permits exact representation of integers in the range –253 to 253 and floating-point magnitudes as large as ±1.7976 x 10308 and as small as ±2.2250 x 10-308.

Numeric literals in JavaScript can be written in a wide variety of ways, including scientific notation. When using scientific notation, the exponent is specified with the letter e (which is not case-sensitive).

Formally (according to the ECMA-262 grammar), decimal literals have one of the following three forms (parentheses indicate optional components):

DecimalDigits.(DecimalDigits)(Exponent)

.DecimalDigits(Exponent)

DecimalDigits(Exponent)

In plain English, this means that all of the following are valid ways to specify numbers:

```10
177.5
-2.71
.333333e77
-1.7E12
3.E-5
128e+100```

Note that you should not include leading zeros in your integers. The reason is that JavaScript also allows numeric literals to be specified in bases other than ten (decimal).

A leading zero indicates to JavaScript that the literal is in a radix other than ten.

Programmers often find it convenient to write numbers in hexadecimal (base-16) notation, particularly when performing bitwise operations. The reason is that it is easier for most people to convert binary to hex than it is to convert binary to decimal. If this doesn’t make any sense to you, don’t fret; if you don’t already know hex, chances are you won’t ever have to.

JavaScript’s hex syntax should be familiar to readers with previous programming experience: a leading zero, followed by the letter x (not case-sensitive), followed by one or more hexadecimal digits. Hexadecimal digits are the numbers zero through nine and letters A through F (not case-sensitive), which represent the values zero through fifteen. The following are examples of legal hexadecimal values:

```0x0
0XF8f00
0x1a3C5e7```

You cannot use an exponent when using hexadecimal notation (nor with octal notation).

 Note While hex may seem to be of limited use in JavaScript used on the Web, consider that color values in HTML are often set in hex, so it may be more important than you think.

#### Octal Literals

Although not officially a part of the ECMA-262 specification, almost all JavaScript implementations allow octal (base-8) numeric literals. Octal literals begin with a leading zero, and octal digits are the numbers zero through seven. The following are all valid octal literals:

```00
0777
024513600```
 Note The Opera browser’s JavaScript implementations, even up to version 5, do not support octal. Future versions should support this data type, but programmers should be aware of this difference when using octal values.

#### Special Values

Numeric data can take on several special values. When a numeric expression or variable exceeds the maximum representable positive value, it takes on the special value Infinity. Likewise, when an expression or variable becomes less than the lowest representable negative value, it takes on the value –Infinity. These values are sticky in the sense that when one is used in an expression with other normal values or itself, it causes the entire expression to evaluate to its value. For example, Infinity minus 100 is still Infinity; it does not become a representable number. All Infinity values compare equal to each other. Similarly, all –Infinity values compare equal.

Although an easier way to get an Infinity value is to divide one by zero, the following code demonstrates what happens when you increment the maximum representable positive value.

```var x = 1.7976931348623157e308;     // set x to max value
x = x + 1e292;                      // increment x
alert(x);                           // show resulting value to user```

This code assigns the maximum positive representation to x, increments its least significant digit, and then shows the user the resulting value x. The result is

The other important special value is NaN, which means “not a number.” Numeric data takes on this value when it is the result of an undefined operation. Common examples of operations that result in NaN are dividing zero by zero, taking the sine of Infinity, and attempting to add Infinity to –Infinity. The NaN value is also sticky, but unlike the infinite values it never compares equal to anything. Because of this, you must use the isNaN() method or compare the value to itself to determine if a value is NaN. The isNaN() method returns a Boolean indicating whether the value is NaN. This method is so important that it is a property of the Global object, so it can be called directly in your scripts. Comparing the value to itself will indicate whether the value is NaN because it is the only value that does not compare equal to itself!

The following example illustrates the use of both techniques:

```var x = 0 / 0;            // assign NaN to x
if (x != x)               // check via self-equality
{
// do something
}
if (isNaN(x))             // check via explicit call
{
// do something
}```

Table 3-1 summarizes these special types.

Table 3-1: Summary of Special Numeric Data Values

Special Value

Result of

Comparisons

Sticky?

Infinity, –Infinity

Number too large or small to be represented

All Infinity values compare equal to each other

Yes

NaN

Undefined operation

NaN never compares equal to anything, even itself

Yes

JavaScript 1.1+ and JScript 2.0+ provide easy access to these special numerical values as properties of the Number object. These properties are shown in Table 3-2, and the following example illustrates how they might be used:

Table 3-2: Properties of the Number Object Relevant to Special Numeric Values

Property

Value

Number.MAX_VALUE

Largest magnitude representable

Number.MIN_VALUE

Smallest magnitude representable

Number.POSITIVE_INFINITY

The special value Infinity

Number.NEGATIVE_INFINITY

The special value –Infinity

Number.NaN

The special value NaN

```// Illustrate that all Infinity values are equal:

var posInf = Number.POSITIVE_INFINITY;
var negInf = Number.NEGATIVE_INFINITY;

// Show the largest magnitude representable:

A complete discussion of functions and constants supported by JavaScript’s Math object can be found in Chapter 7.

 Note Division by zero in JavaScript is somewhat consistent with the calculus. Division of a positive number by zero results in “infinity,” division of a negative number by zero results in “negative infinity,” and division of zero by zero is “undefined” (NaN).

#### Data Representation Issues

The fact that numbers in JavaScript are represented as 64-bit floating-point numbers has some complicated implications and subtle pitfalls. If you’re working with integers, keep in mind that only integers in the range –253 to 253 can be represented exactly. As soon as your value (or an intermediate value in an expression) falls outside of this range, its numeric value becomes an inexact approximation. This can lead to some surprising behavior:

```var x = 9007199254740992;   // 2^53
if (x == x + 1)
alert("True! Large integers are only approximations!");```

Things get really messy if you work with floating-point numbers. Many such values cannot be represented exactly, so you might notice (or worse, not notice) “wrong” answers for even simple computations. For example, consider the following code snippet:

```var x = .3333;
x = x * 5;

One would expect x to contain the value 1.6665. However, the actual result is shown here:

Not only is this not the expected result, but this value will not even compare equal to 1.6665!

A basic rule of thumb is to never directly compare fractional values for equality, and to use rounding to convert numbers into a predetermined number of significant figures. The loss of precision inherent in floating-point arithmetic can be a very serious issue for applications that need to calculate precise values. As a result, it’s probably not a good idea to rely on floating-point arithmetic for important computations unless you have a firm understanding of the issues involved. The topic is far outside the scope of this book, but interested readers can find tutorials on floating-point arithmetic online, and more in-depth discussion in books on numerical analysis or mathematical programming.

### Strings

A string is simply text. In JavaScript, a string is a sequence of characters surrounded by single or double quotes. For example,

`var string1 = "This is a string";`

defines a string value to be stored in string1, as does the code fragment here:

`var string2 = 'So am I';`

Unlike many other languages, JavaScript draws no distinction between single characters and strings of characters. So,

`var oneChar = "s";`

defines a string of length one.

Strings are associated with a String object, which provides methods for manipulation and examination. For example, you can extract characters from strings using the charAt() method.

```var myName = "Thomas";
var thirdLetter = myName.charAt(2);```

Because the characters in strings are enumerated starting with zero (the first position is position zero), this code fragment extracts the third character from the string (o) and assigns it to the variable thirdLetter. You can also determine the length of a string using the length() method:

`var strlen = myName.length();`

This snippet sets strlen to 6. These are just a couple of the numerous methods available with strings that are fully discussed in Chapter 7. However, we do need to cover a few important string details now before moving on to other primitive types.

#### Special Characters and Strings

Any alphabetic, numeric, or punctuation characters can be placed in a string, but there are some natural limitations. For instance, the newline character is the character that causes output to move down one line on your display. Typing this directly into a string using your ENTER key would result in a string literal like this:

```var myString = "This is the first line.
This is the second line."```

which is a syntax error, since the two separate lines appear as two different statements to JavaScript, particularly when semicolons are omitted.

Because of the problem with special characters like returns, quotes, and so on, JavaScript, like most other programming languages, makes use of escape codes. An escape code (also called an escape sequence) is a small bit of text preceded by a backslash (\) that has special meaning. Escape codes let you include special characters without typing them directly into your string. For example, the escape code for the newline character is \n. Using this escape code, we can now correctly define the string literal we previously saw:

`var myString = "This is the first line.\nThis is the second line."`

This example also illuminates an important feature of escape codes: They are interpreted correctly even when found flush with other characters ( . and T in this example).

A list of supported escape codes in JavaScript is shown in Table 3-3.

Table 3-3: Escape Codes Supported in JavaScript

Escape Code

Value

\b

Backspace

\t

Tab (horizontal)

\n

Linefeed (newline)

\v

Tab (vertical)

\f

Form feed

\r

Carriage return

\"

Double quote

\'

Single quote

\\

Backslash

\OOO

Latin-1 character represented by the octal digits OOO. The valid range is 000 to 377.

\xHH

Latin-1 character represented by the hexadecimal digits HH. The valid range is 00 to FF.

\uHHHH

Unicode character represented by the hexadecimal digits HHHH.

#### Character Representation

Close examination of the table of escape codes reveals that JavaScript supports two different character sets. ECMA-262 mandates support for Unicode, so modern JavaScript implementations support it. The Latin character set uses one byte for each character and is therefore a set of 256 possible characters. The Unicode character set has a total of 65,536 characters because each character occupies 2 bytes. Therefore, Unicode includes nearly every printable character in every language on earth. Browser versions prior to Netscape 6 and Internet Explorer 4 use Latin-1 (ISO8859-1), which is a subset of Unicode (some versions of NS4 have partial Unicode support). This distinction will be transparent to most users but can cause problems in a non-English environment.

The following example uses escape codes to assign the string containing the letter B to variables in three different ways. The only difference between the strings is the character set used to represent the character (that is, they all compare equal):

```var inLatinOctal = "\102";
var inLatinHex = "\x42"
var inUnicode = "\u0042";```

#### Quotes and Strings

When it comes to special characters, quotes deserve special notice and you can see in Table 3-3 that there are escape codes for both single and double quotes in JavaScript. If your string is delimited with double quotes, any double quotes within it must be escaped. Similarly, any single quotes in a string delimited with single quotes must be escaped. The reason for this is straightforward: If a quotation mark were not escaped, JavaScript would incorrectly interpret it as the end of the string. The following are examples of validly escaped quotes inside of strings:

```var string1 = "These quotes \"are\" valid!";
var string2 = 'Isn\'t JavaScript great?';```

The following strings are not valid:

```var invalid1 = "This will not work!';
var invalid2 = 'Neither 'will this';```

#### Strings and HTML

The capability for strings to be delimited with either single or double quotes is very useful when one considers that JavaScript is often found inside HTML attributes like onclick. These attributes should themselves be quoted, so flexibility with respect to quoting JavaScript allows programmers to avoid the laborious task of escaping lots of quotes. The following (X)HTML form button illustrates the principle:

`<<input type="button" onclick="document.write('Thanks for clicking!');" />>`

Using double quotes in the document.write would result in the browser interpreting the first such quote as the end of the onclick attribute value, so we use single quotes. The alternative would be to write

`<<input type="button" onclick="document.write(\"Thanks for clicking!")">>`

which is rather awkward.

An example of the use of escape codes and quoting is found next. (X)HTML automatically “collapses” multiple whitespace characters down to one whitespace. So, for example, including multiple consecutive tabs in your HTML shows up as only one space character.

In this example, the <<pre>> tag is used to tell the browser that the text is preformatted and that it should not collapse the whitespaces inside of it. Using <<pre>> allows the tabs in the example to be displayed correctly in the output. The result can be seen in Figure 3-1.

```<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml" lang="en">>
<<title>>String Example<</title>>
<<meta http-equiv="content-type" content="text/html; charset=utf-8" />>
<<body>>
<<pre>>
<<script type="text/javascript">>
<<!–
document.write("Welcome to JavaScript strings.\n");
document.write("This example illustrates nested quotes 'like this.'\n");
document.write("Note how newlines (\\n's) and ");
document.write("escape sequences are used.\n");
document.write("You might wonder, \"Will this nested quoting work?\"");
document.write(" It will.\n");
document.write("Here's an example of some formatted data:\n\n");
document.write("\tCode\tValue\n");
document.write("\t\\n\tnewline\n");
document.write("\t\\\\\tbackslash\n");
document.write("\t\\\"\tdouble quote\n\n");
//–->>
<</script>>
<</pre>>
<</body>>
<</html>> ```

### Boleans

Booleans derive their name from George Boole, the 19th century logician who developed the true/false system of logic upon which digital circuits would later be based. With this in mind, it should come as no surprise that Booleans take on one of two values: true or false.

Comparison expressions such as x << y evaluate to a Boolean value depending upon whether the comparison is true or false. So the condition of a control structure such as if/else is evaluated to a Boolean to determine what code to execute. For example,

```if (x == y)
{
x = x + 1;
} ```

increments x by 1 if the comparison x equal to y is true.

You can use Booleans explicitly to the same effect, as in

```var doIncrement = true;
if (doIncrement)         // if doIncrement is true then increment x
{
x = x + 1;
}```

or

```if (true)                // always increment x
{
x = x + 1;
}```

Booleans are commonly included as object properties indicating an on/off state. For example, the cookieEnabled property of Internet Explorer’s Navigator object (navigator.cookieEnabled) is a Boolean that has value true when the user has persistent cookies enabled and false otherwise. An example of accessing the property is

```if (navigator.cookieEnabled)
{
}
else
{
}```

The result when used in Internet Explorer with persistent cookies enabled is

 Note Some Netscape browsers do not support this property so they will always display the second message (“Persistent cookies are not enabled”). This is because Boolean variables are assigned a default value of false if none is assigned.

### Undefined and Null

The undefined type is used for variables or object properties that either do not exist or have not been assigned a value. The only value an undefined type can have is undefined. For example, declaring a variable without assigning it a value,

`var x;`

gives x the undefined type and value. Accessing a nonexistent object property,

`var x = String.noSuchProperty;`

also results in the assignment of undefined to x.

The null value indicates an empty value; it is essentially a placeholder that represents “nothing.” The distinction between undefined and null values is tricky. In short, undefined means the value hasn’t been set, whereas null means the value has been set to be empty.

Why on earth would the designers of JavaScript permit such a confusing distinction? Without getting into the arcane details, there are actually certain cases where it can be useful, particularly if you’re using the object-oriented features of the language. For example, suppose you’re writing an object whose functionality for a method called doFancyStuff() depends upon a feature offered only by some browsers. You might do some browser detection and define the function doFancyStuff() appropriately if the browser is one that supports the required feature. But if the user has an unrecognized browser, you might set doFancyStuff to null to indicate the method is unavailable. In this way, you can distinguish between the case that the feature is supported (doFancyStuff is a function), the case that the feature isn’t supported (doFancyStuff is null), and the case that the browser detection code hasn’t been run (doFancyStuff is undefined).

There is one further wrinkle to be aware of: the null value is defined as an empty object. Because of this, using the typeof operator on a variable holding null shows its type to be object. In comparison, the type of undefined data is undefined.

#### Distinguishing Between Null and Undefined Data

JavaScript provides the null keyword to enable comparison and assignment of null values. Unfortunately, the undefined keyword exists only in modern browsers (Netscape 6+ and Internet Explorer 5.5+). The resolution lies in the fact that null and undefined values compare equal. So you can check for invalid values by comparing to null. For example, given the declarations,

```var x;
var y = null;```

the following comparisons are true:

```if (x == null)
{
// do something
}
if (x == y)
{
// do something
}
```

However, it is important to note that with the previous declarations, the following,

```   if (z == null)
{
// do something
}```

results in a runtime error. The reason is that z is not merely undefined, it simply does not exist.

JavaScript Debugger     JavaScript Editor