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?
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:
Type | Converted 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 |
Type | Converted 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 |
Type | Converted 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.
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.
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.