11.1 Data Type Conversion
We''ve seen that JavaScript is
an untyped language (or, perhaps more
accurately, a loosely typed or dynamically typed language). This
means, for example, that we don''t have to specify the data type
of a variable when we declare it. Being untyped gives JavaScript the
flexibility and simplicity that are desirable for a scripting
language (although those features come at the expense of rigor, which
is important for the longer, more complex programs often written in
stricter languages such as C and Java). An important feature of
JavaScript''s flexible treatment of data types is the automatic
type conversions it performs. For example, if you pass a number to
the document.write( ) method, JavaScript
automatically converts that value into its equivalent string
representation. Similarly, if you test a string value in the
condition of an if statement, JavaScript
automatically converts that string to a boolean value -- to
false if the string is empty and to
true otherwise.
The basic rule is that when a value of one type is used in a context
that requires a value of some other type, JavaScript automatically
attempts to convert the value as needed. So, for example, if a number
is used in a boolean context, it is converted to a boolean. If an
object is used in a string context, it is converted to a string. If a
string is used in a numeric context, JavaScript attempts to convert
it to a number. Table 11-1 summarizes each of these
conversions -- it shows the conversion that is performed when a
particular type of value is used in a particular context. The
sections that follow the table provide more detail about type
conversions in JavaScript.
Value | Context in which value is used | |||
|---|---|---|---|---|
String | Number | Boolean | Object | |
Undefined value | "undefined" | NaN | false | Error |
null | "null" | 0 | false | Error |
Nonempty string | As is | Numeric value of string or NaN | true | String object |
Empty string | As is | 0 | false | String object |
0 | "0" | As is | false | Number object |
NaN | "NaN" | As is | false | Number object |
Infinity | "Infinity" | As is | true | Number object |
Negative infinity | "-Infinity" | As is | true | Number object |
Any other number | String value of number | As is | true | Number object |
true | "true" | 1 | As is | Boolean object |
false | "false" | 0 | As is | Boolean object |
Object | toString( ) | valueOf( ) or toString( ) or NaN | true | As is |
11.1.1 Object-to-Primitive Conversion
Table 11-1 specifies how JavaScript
objects are converted to
primitive values. Several details of this conversion require
additional discussion, however. First, note that whenever a
non-null object is used in a boolean context, it
converts to true. This is true for all objects
(including all arrays and functions), even wrapper objects that
represent primitive values that convert to false.
For example, all of the following objects convert to
true when used in a boolean context:[1]
[1] Note, though, that in JavaScript 1.1 and 1.2 these objects all
convert to false, which is ECMAScript
compliant.
new Boolean(false) // Internal value is false, but object converts to true
new Number(0)
new String(")
new Array( )
Table 11-1 shows that objects are converted to
numbers by first calling the valueOf(
) method of the object. Most objects
inherit the default valueOf( ) method of Object,
which simply returns the object itself. Since the default
valueOf( ) method does not return a primitive
value, JavaScript next tries to convert the object to a number by
calling its toString( ) method and converting the
resulting string to a number.
This leads to interesting results for
arrays. Recall that the
toString( ) method of arrays converts the array
elements to strings, then returns the result of concatenating these
strings, with commas in between. Therefore, an array with no elements
converts to the empty string, which (as you can see in the table)
converts to the number zero! Also, if an array has a single element
that is a number n, the array converts to
a string representation of n, which is
then converted back to n itself. If an
array contains more than one element, or if its one element is not a
number, the array converts to NaN.[2]
[2] Note, however, that in JavaScript 1.1 and 1.2, when an array is
used in a numeric context it is converted to its length.Table 11-1 specifies how an object is converted
when used in a string context and how it is converted when used in a
numeric context. However, there are a couple of places in JavaScript
where the context is ambiguous! The
+ operator and the comparison
operators (<,
<=, >, and
>=) operate on both numbers and strings, so
when an object is used with one of these operators, it is not clear
whether it should be converted to a number or a string. In most
cases, JavaScript first attempts to convert the object by calling its
valueOf( ) method. If this method returns a
primitive value (usually a number), that value is used. Often,
however, valueOf( ) simply returns the unconverted
object; in this case, JavaScript then tries to convert the object to
a string by calling its toString( ) method.
There is only one exception to this conversion rule: when a
Date object is used
with the + operator, conversion is performed with
the toString( ) method. This exception exists
because Date has both toString( ) and
valueOf( ) methods. When a Date is used with
+, you almost always want to perform a string
concatenation. But when using a Date with the comparison operators,
you almost always want to perform a numeric comparison to determine
which of two times is earlier than the other.
Most objects either don''t have valueOf( )
methods or don''t have valueOf( ) methods
that return useful results. When you use an object with the
+ operator, you usually get string concatenation
rather than addition. When you use an object with a comparison
operator, you usually get string comparison rather than numeric
comparison.
An object that defines a custom valueOf( ) method
may behave differently. If you define a valueOf( )
method that returns a number, you can use arithmetic and other
operators with your object, but adding your object to a string may
not behave as you expect: the toString( ) method
is no longer called, and a string representation of the number
returned by valueOf( ) is concatenated to the
string.
Finally, remember that valueOf( ) is not called
toNumber( ): strictly speaking, its job is to
convert an object to a reasonable primitive value, so some objects
may have valueOf( ) methods that return strings.
11.1.2 Explicit Type Conversions
Table 11-1 listed the
automatic data type conversions
that JavaScript performs. It is also possible to explicitly convert
values from one type to another. JavaScript does not define a cast
operator as C, C++, and Java do, but it does provide similar
facilities for converting data values.
As of JavaScript 1.1 (and the ECMA-262 standard), Number(
)
, Boolean( ),
String( ), and Object( ) may be
called as functions as well as being invoked as constructors. When
invoked in this way, these functions attempt to convert their
arguments to the appropriate type. For example, you could convert any
value x to a string with
String(x) and convert any value
y to an object with Object(y).
There are a few other tricks that can be useful for performing
explicit conversions. To convert a value to a string, concatenate it
with the empty string:
var x_as_string = x + ";
To force a value to a number, subtract zero from it:
var x_as_number = x - 0;
And to force a value to boolean, use the !
operator twice:
var x_as_boolean = !!x;Because of JavaScript''s tendency to automatically convert data
to whatever type is required, explicit conversions are usually
unnecessary. They are occasionally helpful, however, and can also be
used to make your code clearer and more precise.
11.1.3 Converting Numbers to Strings
The number-to-string conversion is probably
the one most often performed in JavaScript. Although it usually
happens automatically, there are a couple of useful ways to
explicitly perform this conversion. We saw two of them above:
var string_value = String(number); // Use the String( ) constructor as a functionThe toString( ) method of the
var string_value = number + "; // Concatenate with the empty string
Another technique for
converting numbers to strings is with the toString(
) method:string_value = number.toString( );
Number object
(primitive numbers are converted to Number objects so that this
method can be called) takes an optional argument that specifies a
radix, or base, for the conversion. If you do not specify the
argument, the conversion is done in base 10. But you can also convert
numbers in other bases (between 2 and 36).[3] For example:
[3] Note that
the ECMAScript specification supports the radix argument to the
toString( ) method, but it allows the method to
return an implementation-defined string for any radix other than 10.
Thus, conforming implementations may simply ignore the argument and
always return a base-10 result. In practice, implementations from
Netscape and Microsoft do honor the requested radix.
var n = 17;
binary_string = n.toString(2); // Evaluates to "10001"
octal_string = "0" + n.toString(8); // Evaluates to "021"
hex_string = "0x" + n.toString(16); // Evaluates to "0x11"
A shortcoming of JavaScript prior to JavaScript 1.5 is that there is
no built-in way to convert a number to a string and specify the
number of decimal places to be
included, or to specify whether exponential notation should be used.
This can make it difficult to display numbers that have traditional
formats, such as numbers that represent monetary values.
ECMAScript v3 and JavaScript 1.5 solve this problem by adding three
new number-to-string methods to the Number class. toFixed(
) converts a number to a string and displays a specified
number of digits after the decimal point. It does not use
exponential notation.
toExponential( ) converts a number to a string
using exponential notation, with one digit before the decimal point
and a specified number of digits after the decimal point.
toPrecision( ) displays a number using the specified
number of significant digits. It uses exponential notation if the
number of significant digits is not large enough to display the
entire integer portion of the number. Note that all three of these
methods round the trailing digits of the resulting string as
appropriate. Consider the following examples:
var n = 123456.789;
n.toFixed(0); // "123457"
n.toFixed(2); // "123456.79"
n.toExponential(1); // "1.2e+5"
n.toExponential(3); // "1.235e+5"
n.toPrecision(4); // "1.235e+5"
n.toPrecision(7); // "123456.8"
11.1.4 Converting Strings to Numbers
We''ve
seen that strings that represent
numbers are automatically converted to actual numbers when used in a
numeric context. As shown earlier, we can make this conversion
explicit:
var number = Number(string_value);
var number = string_value - 0;
The trouble with this sort of string-to-number conversion is that it
is overly strict. It works only with base-10 numbers, and although it
does allow leading and trailing spaces, it does not allow any
non-space characters to appear in the string following the number.
To allow more flexible conversions, you can use parseInt(
)
and parseFloat(
). These functions convert and return any number at the
beginning of a string, ignoring any trailing non-numbers.
parseInt( ) parses only integers, while
parseFloat( ) parses both integers and
floating-point numbers. If a string begins with "0x" or
"0X", parseInt( ) interprets it as a
[4] For example:
[4] The
ECMAScript specification says that if a string begins with
"0" (but not "0x" or "0X"),
parseInt( ) may parse it as an octal number or as
a decimal number. Because the behavior is unspecified, you should
never use parseInt( ) to parse numbers with
leading zeros, unless you explicitly specify the radix to be
used!
parseInt("3 blind mice"); // Returns 3
parseFloat("3.14 meters"); // Returns 3.14
parseInt("12.34"); // Returns 12
parseInt("0xFF"); // Returns 255
parseInt( ) can even take a second argument
specifying the radix (base) of the number to be parsed.
Legal values are between 2 and 36. For example:
parseInt("11", 2); // Returns 3 (1*2 + 1)
parseInt("ff", 16); // Returns 255 (15*16 + 15)
parseInt("zz", 36); // Returns 1295 (35*36 + 35)
parseInt("077", 8); // Returns 63 (7*8 + 7)
parseInt("077", 10); // Returns 77 (7*10 + 7)If
parseInt( ) or parseFloat( )
cannot convert the specified string to a number, it returns
NaN:
parseInt("eleven"); // Returns NaN
parseFloat("$72.47"); // Returns NaN
•
Table of Contents
•
Index
•
Reviews
•
Examples
•
Reader Reviews
•
Errata
JavaScript: The Definitive Guide, 4th Edition
By
David Flanagan
Publisher
: O'Reilly
Pub Date
: November 2001
ISBN
: 0-596-00048-0
Pages
: 936
Slots
: 1
This fourth edition of the definitive reference to
JavaScript, a scripting language that can be embedded
directly in web pages, covers the latest version of the
language, JavaScript 1.5, as supported by Netscape 6 and
Internet Explorer 6. The book also provides complete
coverage of the W3C DOM standard (Level 1 and Level 2),
while retaining material on the legacy Level 0 DOM for
backward compatibility.