Team LiB
Previous Section Next Section

Type Conversion

Automatic type conversion is one of the most powerful features of JavaScript, as well as the most dangerous for the sloppy programmer. Type conversion is the act of converting data of one type into a different type. It occurs automatically in JavaScript when you change the type of data stored in a variable:

var x = "3.14";
x = 3.14;

The type of x changes from string to number. Besides the automatic conversion inherent in JavaScript, it is also possible for programmers to force the conversion using methods like toString() or parseInt().

While it seems straightforward enough, the problem with type conversion also is that it often occurs in less obvious ways, such as when you operate on data with dissimilar types. Consider this code:

var x = "10" - 2;

This example subtracts a number from a string, which should seem very odd at first glance. Yet JavaScript knows that subtraction requires two numbers, so it converts the string "10" into the number 10, performs the subtraction, and stores the number 8 in x.

The truth is that automatic type conversion happens all over the place in JavaScript, any time data is not of the type that might be required for some task. For example, we previously stated that the type of the condition (the part between the parentheses) of flow control statements like if/else is Boolean. This means that given a statement like this,

var x = "false";  // a string
if (x) 
  {
   alert("x evaluated to the Boolean value true");
  }

the interpreter must somehow convert the given string to a Boolean in order to determine if the body of the if statement should be executed.

Similarly, since HTML documents are made up of text, the interpreter must convert the number in the following example to a string in order to write it into the page:

var x = 21.84e22;    // a number
document.write(x);   // x is automatically converted to a string here

The important question is this: what rules does the interpreter use to carry out these conversions?

Conversion Rules for Primitive Types

The type conversion rules for primitive types are given in Tables 3-5, 3-6, and 3-7. You can use these tables to answer questions like what happens in this example:

Table 3-5: Result of Conversion to a Boolean
TypeConverted to Boolean

Undefined

false

Null

false

Number

false if 0 or NaN, else true

String

false if string length is 0, else true

Other object

true

Table 3-6: Result of Converting to a Number
TypeConverted to Number

Undefined

NaN

Null

0

Boolean

1 if true, 0 if false

String

The numeric value of the string if it looks like a number, else NaN

Other object

NaN

Table 3-7: Result of Converting to a String
TypeConverted to a String

Undefined

"Undefined"

Null

"Null"

Boolean

"True" if true, "false" if false

Number

"NaN", "0", or the string representation of the numeric value

Other object

Value of object's toString() method if it exists, else "undefined"

var x = "false";  // a string
if (x) 
  {
    alert("x evaluated to the Boolean value true");
  }

Since every string but the empty string ("") converts to the Boolean value of true, the conditional is executed and the user is shown the alert.

These type conversion rules mean that comparisons such as

1 == true

0 == ""

are true. But sometimes you don’t want type conversion to be applied when checking equality, so JavaScript provides the strict equality operator (===). This operator evaluates to true only if its two operands are equal and they have the same type. So, for example, the following comparisons would be false:

1 === true

0 === ""

0 === "0"

How the JavaScript interpreter determines the type required for most operators is fairly natural and isn’t required knowledge for most developers. For example, when performing arithmetic, types are converted into numbers, then computations are performed.

One important exception is the + operator. The + operator performs addition on numbers but also serves as the concatenation operator for strings. Because string concatenation has precedence over numeric addition, + will be interpreted as string concatenation if any of the operands are strings. For example, both statements,

x = "2" + "3";
x = "2" + 3;

result in the assignment of the string "23" to x. The numeric 3 in the second statement is automatically converted to a string before concatenation is applied.

Promotion of Primitive Data to Objects

It was previously mentioned that there is an object corresponding to each primitive type. These objects provide useful methods for manipulating primitive data. For example, the String object provides a method to convert a string to lowercase: toLowerCase(). You can invoke this method on a String object:

var myStringObject = new String("ABC");
var lowercased = myStringObject.toLowerCase();

The interesting aspect of JavaScript is that you can also invoke it on primitive string data:

var myString = "ABC";
var lowercased = myString.toLowerCase();

as well as on literals:

var lowercased = "ABC".toLowerCase();

The key insight is that JavaScript automatically converts the primitive data into its corresponding object when necessary. In the preceding examples, the interpreter knew that the toLowerCase method requires a String object, so it automatically and temporarily converted the primitive string into the object in order to invoke the method.

Explicit Type Conversion

The reality of most programming tasks is that it is probably better to perform type conversion manually than trust the interpreter to do it for you. One situation when this is definitely the case is when processing user input. User input acquired through use of dialog boxes and (X)HTML forms usually comes in strings. It is often necessary to explicitly convert such data between string and number types to prevent operators like + from carrying out the wrong operation (for example, concatenation instead of addition, or vice versa). JavaScript provides several tools for carrying out explicit type conversion, for example, objects’ toString() method and the parseInt() and parseFloat() methods of the Global object. These methods are discussed in depth in later chapters (particularly Chapter 7) as their applications become more apparent.


Team LiB
Previous Section Next Section