JavaScript – Type Conversions

JavaScript is very flexible about the types of values it
requires. We’ve seen this for booleans: when JavaScript expects a
boolean value, you may supply a value of any type, and JavaScript will
convert it as needed. Some values (“truthy” values) convert to
true and others (“falsy” values)
convert to false. The same is true
for other types: if JavaScript wants a string, it will convert
whatever value you give it to a string. If JavaScript wants a number,
it will try to convert the value you give it to a number (or to
NaN if it cannot perform a
meaningful conversion). Some examples:

10 + " objects"     // => "10 objects".  Number 10 converts to a string
"7" * "4"           // => 28: both strings convert to numbers
var n = 1 - "x";    // => NaN: string "x" can't convert to a number
n + " objects"      // => "NaN objects": NaN converts to string "NaN"

Table 3-2 summarizes how values
convert from one type to another in JavaScript. Bold entries in the
table highlight conversions that you may find surprising. Empty cells
indicate that no conversion is necessary and none is performed.

Table 3-2. JavaScript type conversions

Value

Converted to:

String

Number

Boolean

Object

undefined

"undefined"

NaN

false

throws TypeError

null

"null"

0

false

throws TypeError

true

"true"

1

new
Boolean(true)

false

"false"

0

new
Boolean(false)

""
(empty string)

0

false

new
String("")

"1.2" (nonempty,
numeric)

1.2

true

new
String("1.2")

"one" (nonempty,
non-numeric)

NaN

true

new
String("one")

0

"0"

false

new Number(0)

-0

"0"

false

new
Number(-0)

NaN

"NaN"

false

new
Number(NaN)

Infinity

"Infinity"

true

new
Number(Infinity)

-Infinity

"-Infinity"

true

new
Number(-Infinity)

1
(finite, non-zero)

"1"

true

new Number(1)

{}
(any object)

see Object to Primitive Conversions

see Object to Primitive Conversions

true

[]
(empty array)

""

0

true

[9]
(1 numeric elt)

"9"

9

true

['a'] (any other
array)

use join() method

NaN

true

function(){} (any
function)

see Object to Primitive Conversions

NaN

true

The primitive-to-primitive conversions shown in the table are
relatively straightforward.
Conversion to boolean was already discussed in Boolean Values. Conversion to strings is well-defined for all
primitive values. Conversion to numbers is just a little trickier.
Strings that can be parsed as numbers convert to those numbers.
Leading and trailing spaces are allowed, but any leading or trailing
nonspace characters that are not part of a numeric literal cause the
string-to-number conversion to produce NaN. Some numeric conversions may seem
surprising: true converts to 1, and
false and the empty string "" convert to 0.

Primitive-to-object conversions are straightforward: primitive
values convert to their wrapper object (Wrapper Objects)
as if by calling the String(),
Number(), or Boolean() constructor. The exceptions are
null and undefined: any attempt to use these values
where an object is expected raises a TypeError exception rather than
performing a conversion.

Object-to-primitive conversion is somewhat more complicated, and
it is the subject of Object to Primitive Conversions.

Conversions and Equality

Because JavaScript can convert values flexibly, its == equality operator is also flexible with
its notion of equality. All of the following comparisons are true,
for example:

null == undefined // These two values are treated as equal.
"0" == 0          // String converts to a number before comparing.
0 == false        // Boolean converts to number before comparing.
"0" == false      // Both operands convert to numbers before comparing.

Equality and Inequality Operators explains exactly what
conversions are performed by the == operator in order to determine whether
two values should be considered equal, and it also describes the
strict equality operator === that
does not perform conversions when testing for equality.

Keep in mind that convertibility of one value to another does
not imply equality of those two values. If undefined is used where a boolean value is
expected, for example, it will convert to false. But this does not mean that
undefined == false. JavaScript
operators and statements expect values of various types, and perform
conversions to those types. The if statement converts undefined to false, but the == operator never attempts to convert its
operands to booleans.

Explicit Conversions

Although JavaScript performs many type conversions
automatically, you may sometimes need to perform an explicit
conversion, or you may prefer to make the conversions explicit to
keep your code clearer.

The simplest way to perform an explicit type conversion is to
use the Boolean(), Number(), String(), or Object() functions. We’ve already seen
these functions as constructors for wrapper objects (in Wrapper Objects). When invoked without the new operator, however, they work as
conversion functions and perform the conversions summarized in
Table 3-2:

Number("3")           // => 3
String(false)         // => "false"  Or use false.toString()
Boolean([])           // => true
Object(3)             // => new Number(3)

Note that any value other than null or undefined has a toString() method and the result of this
method is usually the same as that returned by the String() function. Also note that Table 3-2 shows a TypeError if you attempt to
convert null or undefined to an object. The Object() function does not throw an
exception in this case: instead it simply returns a newly created
empty object.

Certain JavaScript operators perform implicit type
conversions, and are sometimes used for the purposes of type
conversion. If one operand of the + operator is a string, it converts the
other one to a string. The unary + operator converts its operand to a
number. And the unary ! operator
converts its operand to a boolean and negates it. These facts lead
to the following type conversion idioms that you may see in some
code:

x + ""           // Same as String(x)
+x               // Same as Number(x).  You may also see x-0
!!x              // Same as Boolean(x). Note double !

Formatting and parsing numbers are common tasks in computer
programs and JavaScript has specialized functions and methods that
provide more precise control over number-to-string and
string-to-number conversions.

The toString() method
defined by the Number class accepts 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. However,
you can also convert numbers in other bases (between 2 and 36). For
example:

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"

When working with financial or scientific data, you may want
to convert numbers to strings in ways that give you control over the
number of decimal places or the number of significant digits in the
output, or you may want to control whether exponential notation is
used. The Number class defines three methods for these kinds of
number-to-string conversions. toFixed() converts a number to a string
with a specified number of digits after the decimal point. It never
uses 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
(which means that the number of significant digits is one larger
than the value you specify). toPrecision() converts a number to a
string with the number of significant digits you specify. 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 methods round the trailing digits or pad with
zeros as appropriate. Consider the following examples:

var n = 123456.789;
n.toFixed(0);         // "123457"
n.toFixed(2);         // "123456.79"
n.toFixed(5);         // "123456.78900"
n.toExponential(1);   // "1.2e+5"
n.toExponential(3);   // "1.235e+5"
n.toPrecision(4);     // "1.235e+5"
n.toPrecision(7);     // "123456.8"
n.toPrecision(10);    // "123456.7890"

If you pass a string to the Number() conversion function, it attempts
to parse that string as an integer or floating-point literal. That
function only works for base-10 integers, and does not allow
trailing characters that are not part of the literal. The parseInt() and parseFloat() functions (these are global
functions, not methods of any class) are more flexible. 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
hexadecimal number.[2] Both parseInt() and
parseFloat() skip leading
whitespace, parse as many numeric characters as they can, and ignore
anything that follows. If the first nonspace character is not part
of a valid numeric literal, they return NaN:

parseInt("3 blind mice")     // => 3
parseFloat(" 3.14 meters")   // => 3.14
parseInt("-12.34")           // => -12
parseInt("0xFF")             // => 255
parseInt("0xff")             // => 255
parseInt("-0XFF")            // => -255
parseFloat(".1")             // => 0.1
parseInt("0.1")              // => 0
parseInt(".1")               // => NaN: integers can't start with "."
parseFloat("$72.47");        // => NaN: numbers can't start with "$"

parseInt() accepts an
optional second argument specifying the radix (base) of the number
to be parsed. Legal values are between 2 and 36. For example:

parseInt("11", 2);           // => 3 (1*2 + 1)
parseInt("ff", 16);          // => 255 (15*16 + 15)
parseInt("zz", 36);          // => 1295 (35*36 + 35)
parseInt("077", 8);          // => 63 (7*8 + 7)
parseInt("077", 10);         // => 77 (7*10 + 7)

Object to Primitive Conversions

Object-to-boolean conversions are trivial: all objects
(including arrays and functions) convert to true. This is so even for wrapper objects:
new Boolean(false) is an object
rather than a primitive value, and so it converts to true.

Object-to-string and object-to-number conversions are
performed by invoking a method of the object to be converted. This
is complicated by the fact that JavaScript objects have two
different methods that perform conversions, and it is also
complicated by some special cases described below. Note that the
string and number conversion rules described here apply only to
native objects. Host objects (defined by web browsers, for example)
can convert to numbers and strings according to their own
algorithms.

All objects inherit two conversion methods. The first is
called toString(), and its job is
to return a string representation of the object. The default
toString() method does not return
a very interesting value (though we’ll find it useful in Example 6-4):

({x:1, y:2}).toString()    // => "[object Object]"

Many classes define more specific versions of the toString() method. The toString() method of the Array class, for
example, converts each array element to a string and joins the
resulting strings together with commas in between. The toString() method of the Function class
returns an implementation-defined representation of a function. In
practice, implementations usually convert user-defined functions to
strings of JavaScript source code. The Date class defines a toString() method that returns a
human-readable (and JavaScript-parsable) date and time string. The
RegExp class defines a toString()
method that converts RegExp objects to a string that looks like a
RegExp literal:

[1,2,3].toString()                  // => "1,2,3"
(function(x) { f(x); }).toString()  // => "function(x) {\n    f(x);\n}"
/\d+/g.toString()                   // => "/\\d+/g"
new Date(2010,0,1).toString()  // => "Fri Jan 01 2010 00:00:00 GMT-0800 (PST)"

The other object conversion function is called valueOf(). The job of this method is less
well-defined: it is supposed to convert an object to a primitive
value that represents the object, if any such primitive value
exists. Objects are compound values, and most objects cannot really
be represented by a single primitive value, so the default valueOf() method simply returns the object
itself rather than returning a primitive. Wrapper classes define
valueOf() methods that return the
wrapped primitive value. Arrays, functions, and regular expressions
simply inherit the default method. Calling valueOf() for instances of these
types simply returns the object itself. The Date class defines a
valueOf() method that returns the
date in its internal representation: the number of milliseconds
since January 1, 1970:

var d = new Date(2010, 0, 1);   // January 1st, 2010, (Pacific time)
d.valueOf()                     // => 1262332800000

With the toString() and
valueOf() methods explained, we
can now cover object-to-string and object-to-number conversions. Do
note, however, that there are some special cases in which JavaScript
performs a different object-to-primitive conversion. These special
cases are covered at the end of this section.

To convert an object to a string, JavaScript takes these
steps:

  • If the object has a toString() method, JavaScript calls
    it. If it returns a primitive value, JavaScript converts that
    value to a string (if it is not already a string) and returns
    the result of that conversion. Note that primitive-to-string
    conversions are all well-defined in Table 3-2.

  • If the object has no toString() method, or if that method
    does not return a primitive value, then JavaScript looks for a
    valueOf() method. If the
    method exists, JavaScript calls it. If the return value is a
    primitive, JavaScript converts that value to a string (if it is
    not already) and returns the converted value.

  • Otherwise, JavaScript cannot obtain a primitive value from
    either toString() or valueOf(), so it throws a
    TypeError.

To convert an object to a number, JavaScript does the same
thing, but it tries the valueOf() method first:

  • If the object has a valueOf() method that returns a
    primitive value, JavaScript converts (if necessary) that
    primitive value to a number and returns the result.

  • Otherwise, if the object has a toString() method that returns a
    primitive value, JavaScript converts and returns the
    value.

  • Otherwise, JavaScript throws a TypeError.

The details of this object-to-number conversion explain why an
empty array converts to the number 0 and why an array with a single
element may also convert to a number. Arrays inherit the default
valueOf() method that returns an
object rather than a primitive value, so array-to-number conversion
relies on the toString() method.
Empty arrays convert to the empty string. And the empty string
converts to the number 0. An array with a single element converts to
the same string that that one element does. If an array contains a
single number, that number is converted to a string, and then back
to a number.

The + operator in
JavaScript performs numeric addition and string concatenation. If
either of its operands is an object, JavaScript converts the object
using a special object-to-primitive conversion rather than the
object-to-number conversion used by the other arithmetic operators.
The == equality operator is
similar. If asked to compare an object with a primitive value, it
converts the object using the object-to-primitive
conversion.

The object-to-primitive conversion used by + and == includes a special case for Date
objects. The Date class is the only predefined core JavaScript type
that defines meaningful conversions to both strings and numbers. The
object-to-primitive conversion is basically an object-to-number
conversion ( valueof() first) for
all objects that are not dates, and an object-to-string conversion
( toString() first) for Date
objects. The conversion is not exactly the same as those explained
above, however: the primitive value returned by valueOf() or toString() is used directly without being
forced to a number or string.

The < operator and the
other relational operators perform object-to-primitive conversions
like == does, but without the
special case for Date objects: any object is converted by trying
valueOf() first and then toString(). Whatever primitive value is
obtained is used directly, without being further converted to a
number or string.

+, ==, !=
and the relational operators are the only ones that perform this
special kind of string-to-primitive conversions. Other operators
convert more explicitly to a specified type and do not have any
special case for Date objects. The - operator, for example, converts its
operands to numbers. The following code demonstrates the behavior of
+, -, ==,
and > with Date
objects:

var now = new Date();     // Create a Date object
typeof (now + 1)          // => "string": + converts dates to strings
typeof (now - 1)          // => "number": - uses object-to-number conversion
now == now.toString()     // => true: implicit and explicit string conversions
now > (now -1)            // => true: > converts a Date to a number


[2] In ECMAScript 3, parseInt() may parse a string that
begins with “0” (but not “0x” or “0X”) 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! In ECMAScript 5, parseInt() only parses octal numbers
if you explicitly pass 8 as the second argument.

Comments are closed.