Chapter 2. Type Conversion

Iron Man, Superman, Batman, Spider-Man, X-Men, and countless other superheroes have many traits in common. Most have a distinctive costume, unwavering morals, underlying motif, secret identity, supervillains to fight, and, of course, extraordinary powers. Those powers may or may not be innate, though. For example, Clark Kent doesn't need his Superman costume to fly, but Tony Stark would drop like a stone without his Iron Man armor.

JavaScript values of object type or array and function subtypes are like Superman or Spider-Man. They innately have extraordinary powers, referred to as members or methods. On the other hand, values of the string, number, or boolean type are like Iron Man or Batman in that they need to put on their costume, referred to as a wrapper, to have extraordinary powers.

So, just as seeing the bat signal appear in the night sky over Gotham City tells Bruce Wayne to put on the bat suit in order to become Batman, seeing the . operator appear to their right tells a string, number, or boolean to put on a wrapper in order to become an object.

Conversely, just as Batman returns to being Bruce Wayne after defeating the Joker, Penguin, or Catwoman, a wrapper object returns to being a string, number, or boolean after invoking a method. To convert a string, number, or boolean to a wrapper object, JavaScript invokes String(), Number(), or Boolean(). Those are referred to as constructor functions. To reverse the conversion, that is, to convert a wrapper object back to a string, number, or boolean, JavaScript invokes valueOf() on the wrapper.

Insofar as JavaScript converts string, number, and boolean values to and from wrapper objects behind the scenes, we just need to explore their features. Moreover, string wrappers are useful, but those for numbers and booleans are not. So, we won't waste time on those.

String Members

Open firebug.html in Firefox, and then press F12 to enable Firebug. If you're just joining us, flip back to the preface for details on how to do this. In Chapter 1, you learned how to glue one string to another with the + operator. concat() does the same thing. So in Firebug, let's glue "man" to "Bat" by way of the + operator and concat() method, verifying our work with Figure 2-1:

"Bat" + "man";
// "Batman"
"Bat".concat("man");
// "Batman"
concat() works like the + operator.

Figure 2-1. concat() works like the + operator.

If you want to append more than one string, separate them with commas. JavaScript will then sequentially append the parameters to the initial string. Try it in Firebug by entering and running the following sample:

"Spider".concat("-", "Man");
// "Spider-Man"

One thing to note regarding every String method we explore in this chapter is that they return a new, modified string but do not modify the original string. More formally, we would say strings are immutable. To illustrate the point, let's invoke concat() on a variable containing a string like so, verifying our work with Figure 2-2:

var name = "Super";
name.concat("man");
// "Superman"
name;
// "Super"
String methods do not modify the initial string.

Figure 2-2. String methods do not modify the initial string.

As you can see, JavaScript used the string in name as the basis for the modification we wanted done. The concat() method returned "Superman", but name still contains "Super".

With this in mind, you will likely want to save the return value of a String method to another variable. Otherwise, it's as if the modification never happened. Let's do so, verifying our work with Figure 2-3:

var pre = "Bat";
var post = pre.concat("man");
pre;
// "Bat"
post;
// "Batman";
Typically you will want to save the return value. Otherwise, it's lost.

Figure 2-3. Typically you will want to save the return value. Otherwise, it's lost.

If you do not need the original string, you can simply overwrite it with the return value like so. Note that this does not modify the original string. Rather, it writes a new string to the variable:

var pre = "Bat";
pre = pre.concat("man");
pre;
// "Batman"

Oddly enough, it's quite common not to save the return value of a string method. Say you want to do a case-insensitive comparison of one string to another. Perhaps you're unsure whether a visitor will search for "Superman", "superman", or "SuperMan". To do so, you would call toLowerCase() on a string, comparing the return value, a lowercase literal, to another lowercase literal like so, verifying your work with Figure 2-4:

var hero = "Superman";
hero.toLowerCase() === "superman";
// true
But it's also common not to save the return value.

Figure 2-4. But it's also common not to save the return value.

Understanding the three ways to use the return value of any String method is as vital as knowing what it does. Here's a recap:

  • You can save the return value to a new variable.

  • You can replace the string in the original variable with the return value.

  • You can immediately use the return value as an operand for an operator such as ===.

Note that the first two ways apply to object members, array elements, and function parameters, too.

In addition to concat(), string wrappers provide the following members. Note that we'll explore only the vital ones. Note too that, except for String.fromCharCode(), we'll need to replace identifier String with a string literal or string expression, typically just the name of a variable, member, element, or parameter containing a string. However, any expression returning a string will do.

String.charAt()
String.charCodeAt()
String.concat()
String.fromCharCode()
String.indexOf()
String.lastIndexOf()
String.length
String.localeCompare()
String.match()
String.replace()
String.search()
String.slice()
String.split()
String.substring()
String.substr()
String.toLocaleLowerCase()
String.toLocaleUpperCase()
String.toLowerCase()
String.toUpperCase()

Note

We use String.fromCharCode() as it is because it is a static method. This means JavaScript does not use the String() constructor method to create a string when we call this method.

Determining the Number of Characters

For the string "Batman", Firefox would create a wrapper like the following object literal. Recall from Chapter 1 that an object may have elements just like an array. So, this object contains six elements numbered 0 to 5.

{"0": "B", "1": "a", "2": "t", "3": "m", "4": "a", "5": "n"}

With this in mind, we can query characters in "Batman" numerically with the [] operator. Try doing so in Firebug, verifying your work with Figure 2-5:

"Batman"[3];
// "m"
"Batman"[0];
// "B"
Querying elements in a wrapper object

Figure 2-5. Querying elements in a wrapper object

String wrappers have a length member equal to the number of elements. That is to say, length is equal to the number of characters in the string. Try querying length for the Incredibles and a few of their supervillains.

"Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack".length;
// 51
"Underminer, Syndrome, Bomb Voyage".length;
// 33

Just as you can query the final element in an array by subtracting 1 from its length member, you can query the final character, which is to say the final element, in a string the very same way. Similarly, subtracting 2 from length returns the second-from-last character, subtracting 3 returns the third-from-last character, and so on:

var parrFamily = "Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack";
parrFamily[parrFamily.length - 1];
// "k"
parrFamily[parrFamily.length - 15];
// "D"

Querying elements in a wrapper object with the [] operator is a Firefox proprietary feature that is helpful in understanding the way strings are represented with wrapper objects. However, ECMAScript does not require JavaScript interpreters to support it. So, Internet Explorer and other browsers don't. Therefore, it's best to query characters the standard way—by passing the element's index, in other words, its number, to charAt(). Though not as convenient, doing so works cross-browser. Try the following sample in Firebug, verifying your work with Figure 2-6:

var parrFamily = "Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack";
parrFamily.charAt(7);
// "r"
parrFamily.charAt(parrFamily.length - 1);
// "k"
Querying elements the standard way is less convenient but works cross-browser.

Figure 2-6. Querying elements the standard way is less convenient but works cross-browser.

Decoding or Encoding Characters

For nonkeyboard characters, it's typically simpler to work with the Unicode encoding than the character. For example, Dr. Otto Günther Octavius is the secret identity of one of Spider-Man's archenemies, Doctor Octopus. Rather than try to type the ü in Günther, pass its Unicode encoding (252) to String.fromCharCode() like so in Firebug, verifying your work with Figure 2-7:

var id = "Dr. Otto G" + String.fromCharCode(252) + "nther Octavius";
id;
// "Dr. Otto Günther Octavius"
String.fromCharCode() provides a way to insert nonkeyboard characters.

Figure 2-7. String.fromCharCode() provides a way to insert nonkeyboard characters.

Conversely, it's simpler to encode the ü and work with 252, say in a comparison, than to try to type the ü. To do so, pass the index to charCodeAt(), which returns the Unicode encoding rather than the character, as its partner in crime, charAt(), would. Although the following two comparisons are equivalent, I'm guessing you were only able to key in the first in Firebug. Figure 2-8 displays both, however.

var id = "Dr. Otto G" + String.fromCharCode(252) + "nther Octavius";
id.charCodeAt(10) === 252;
// true
id.charAt(10) === "ü";
// true
charCodeAt() is useful for encoding nonkeyboard characters.

Figure 2-8. charCodeAt() is useful for encoding nonkeyboard characters.

Converting Case

In addition to decoding and encoding characters with String.fromCharCode() and charCodeAt(), you can convert their case to lowercase or uppercase with toLowerCase() or toUpperCase(). For example, fight scenes in Batman comic books would have onomatopoeic words such as pow, bam, and zonk superimposed in uppercase. So in Firebug, let's add some pop to some lowercase onomatopoeic words with the help of toUpperCase():

"Pow! Bam! Zonk!".toUpperCase();
// "POW! BAM! ZONK!"

Conversely, if the Penguin were to quietly spray a paralytic gas on Batman and Robin with his umbrella, we might want to tone down "PSST...ZZZZ" with toLowerCase(), verifying both samples with Figure 2-9. Note that toLowerCase() or toUpperCase() only manipulate letters. So, nothing weird like the "!" changing to a "1" will happen.

"PSST...ZZZZ".toLowerCase();
// "psst...zzzz"
Converting to uppercase or lowercase

Figure 2-9. Converting to uppercase or lowercase

Turkish has dotted and dotless versions of i:

  • İ i

  • I ı

The lowercase version of I is ı, not i. Conversely, the uppercase version of i is İ, not I. So for Turkish, toLowerCase() and toLowerCase() would mess up the i pairings. For Turkish and other alphabets with dotted and dotless i versions such as Azerbaijani, Kazakh, Tatar, and Crimean Tatar, JavaScript provides a second pair of methods, toLocaleLowerCase() and toLocaleUpperCase(), which get the i conversions right:

"I".toLowerCase();
// "i"
"i".toUpperCase()
// "I"
"I".toLocaleLowerCase();
// "ı"
"i".toLocaleUpperCase()
// "İ"

Note

toLocaleLowerCase() and toLocaleUpperCase() convert case based on your OS settings. You'd have to change those settings to Turkish for the previous sample to work. Or just take my word for it!

Locating a Substring

Sometimes you will want to search a string for a smaller string, referred to as a substring. For example, "man" is a substring of "Batman" and "Catwoman". One way to do so is with indexOf(), which works with two parameters:

  • The substring to search for

  • An optional index for where to begin the search

If the substring is found, indexOf() returns the index of the first matched character. Otherwise, it returns −1 to convey failure. So in Firebug, let's determine where the substring "Ghost" begins in a literal containing some of Iron Man's archenemies:

"Iron Monger, Titanium Man, Madame Masque, Ghost, Mandarin".indexOf("Ghost");
// 42

Try doing so indirectly through a variable containing the literal. Pass in "Mandarin" and then "Green Goblin", who is Spider-Man's responsibility. So, as Figure 2-10 displays, JavaScript confirms this by returning −1:

var villains = "Iron Monger, Titanium Man, Madame Masque, Ghost, Mandarin";
villains.indexOf("Mandarin");
// 49
villains.indexOf("Green Goblin");
-1
indexOf() returns −1 to convey failure.

Figure 2-10. indexOf() returns −1 to convey failure.

Note that you may call indexOf() on any expression evaluating to string. Those include literals and variables as well as return values for operators or functions, which we'll cover in Chapters 3 and 6, respectively.

indexOf() optionally takes a second parameter telling JavaScript where to begin looking for a substring. Insofar as indexOf() returns the location of the first match, the second parameter provides a way to locate a recurring substring, such as "Man" in our list of Iron Man supervillains. So, we could locate the first and second occurrences of "Man" like so in Firebug. Note that JavaScript evaluates villains.indexOf("Man") + 1, which returns 23, prior to passing the parameter to indexOf(). Verify your work with Figure 2-11:

var villains = "Iron Monger, Titanium Man, Madame Masque, Ghost, Mandarin";
villains.indexOf("Man");
// 22
villains.indexOf("Man", villains.indexOf("Man") + 1);
// 49
Locating the second occurence of "Man"

Figure 2-11. Locating the second occurence of "Man"

indexOf() has a partner in crime named lastIndexOf() that searches upstream, from the end of a string to the beginning. Insofar as the second occurrence of "Man" is also the last, we could therefore rewrite the previous sample like so:

var villains = "Iron Monger, Titanium Man, Madame Masque, Ghost, Mandarin";
villains.lastIndexOf("Man");
// 49

Clipping a Substring

Sometimes you may want to cut a slice from a string. To do so, pass two parameters to slice():

  • The index of the first character in the slice

  • The index of the first character after the slice

So, to slice n characters beginning at index i, pass i for the first parameter and i + n for the second parameter. Just remember that character indexes begin at 0.

"Superman, Batman, Spider-Man, Iron Man".slice(18, 24);
// "Spider"

Note that, if you omit the second parameter, JavaScript cuts a slice from the index in the first parameter all the way the end of the string. That is, it sets the second index to length. So, the following two samples do the same thing:

var heroes = "Superman, Batman, Spider-Man, Iron Man";
heroes.slice(30);
// "Iron Man"
heroes.slice(30, heroes.length);
// "Iron Man"

Note too that, if either parameter is negative, JavaScript adds length to them. Verify your work with Figure 2-12:

heroes.slice(10, −22);
// "Batman"
Clipping a substring with slice()

Figure 2-12. Clipping a substring with slice()

Replacing a Substring

If you want to replace part of a string, invoke its replace() method, which works with two parameters:

  • The string to remove

  • The string to insert

However, the first parameter may be a string or RegExp object (we'll explore RegExp objects in Chapter 5), and the second parameter can be a string or a function that returns a string.

Note

Don't worry about the RegExp examples in this chapter; they're fairly simple and are included to keep some common tasks in one place. This means you'll learn the best ways to replace substrings here, rather than having to wait until Chapter 5 to learn all the techniques.

To begin with, we'll make both parameters strings. So, double-clear Firebug as detailed in the preface, and let's use replace() to turn Batman into Superman like so:

"Batman".replace("Bat", "Super");
// "Superman"

One thing to note when passing a string rather than a RegExp object for the first parameter is that replace() swaps only the first occurrence. To illustrate the point, run the following sample in Firebug:

"Batman and Batgirl".replace("Bat", "Super");
// "Superman and Batgirl"

To replace two or more occurrences of a search string like "Bat" with a replacement string like "Super", the first parameter must be a RegExp object marked with a g flag, which tells JavaScript to find all matches rather than just the first match. So, just as a primer for Chapter 5, if we make the first parameter in the previous sample a very simple RegExp literal, /Bat/g, we get the desired duo. Verify this and the previous two samples with Figure 2-13:

"Batman and Batgirl".replace(/Bat/g, "Super");
// "Superman and Supergirl"
Replacing a substring with replace()

Figure 2-13. Replacing a substring with replace()

Now let's create a title-casing function named titleCase() to pass as the second parameter so that we can replace each hero's name with its title-case version. JavaScript will pass titleCase() the matched text, which we can refer to as m within the function block. There we'll chain invocations of slice() and toUpperCase() in order to convert the first letter in m to uppercase. Then we'll glue that to a slice containing every character in m but the first and return that as the replacement string.

var titleCase = function(m) {
  return m.slice(0,1).toUpperCase() + m.slice(1);
};

If we then pass a RegExp literal that matches words, /w+/g, for the first parameter, JavaScript will pass each word in the string we call replace() to titleCase(). Let's try this on "batman, spider-man, iron man", verifying our work with Figure 2-14. Note that JavaScript invokes titleCase() five times, once for each of the following matches: "batman", "spider", "man", "iron", and "man".

var titleCase = function(m) {
  return m.slice(0,1).toUpperCase() + m.slice(1);
};
"batman, spider-man, iron man".replace(/w+/g, titleCase);
// "Batman, Spider-Man, Iron Man"
The second parameter to replace() may be a function.

Figure 2-14. The second parameter to replace() may be a function.

Splitting a String into an Array of Smaller Strings

If you want to divide a string into smaller strings, pass the split() method a divider. It will then split the string into smaller strings, referred to as substrings, based on where the divider occurs. Those substrings do not include the divider and are returned in an array by split(). Double-clear Firebug, and let's divvy up a list of Spider-Man's archenemies relative to a comma followed by a space. We'll pass ", " to split() like so, verifying our work with Figure 2-15:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, Sandman";
villains.split(", ");
// ["Green Goblin", "Doctor Octopus", "Venom", "Hobgoblin", "Sandman"]
Splitting a string into smaller strings with split()

Figure 2-15. Splitting a string into smaller strings with split()

Say the final villain is prefaced by ", and " rather than ", ". That is to say, we want to divvy up a string based on two dividers, ", " or ", and ". This can't be done by passing a string divider. Rather, we'd need to pass in a RegExp literal to match both dividers:

/, (?:and)?/g

Don't worry, this won't look like gobbledygook by the end of Chapter 5 (note how you can identify the dividers in the expression, and we're using /g again). Try the following sample in Firebug, verifying your work with Figure 2-16:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains.split(/, (?:and )?/g);
// ["Green Goblin", "Doctor Octopus", "Venom", "Hobgoblin", "Sandman"]
Passing a RegExp object to split()

Figure 2-16. Passing a RegExp object to split()

Do you remember from Chapter 1 how you would query the array returned by split()?

Uh-huh. By passing an index to the [] operator. So, to return the fourth element, "Hobgoblin", we'd pass [] the index 3 since JavaScript numbers elements beginning with 0:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains.split(/, (?:and )?/g)[3];
// "Hobgoblin"

That worked well. But what happened to the array? It's not in villains, as Figure 2-17 displays:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains.split(/, (?:and )?/g)[3];
// "Hobgoblin"
villains;
// "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman"
Where'd the array of substrings go?

Figure 2-17. Where'd the array of substrings go?

As noted earlier in the chapter, split(), like any other string method, does not modify the string value it's called upon. Rather, split() returns a new value. We'd need to save the array to a new variable or overwrite villains. Let's do the latter, verifying our work with Figure 2-18:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains = villains.split(/, (?:and )?/g);
villains[1];
// "Doctor Octopus"
Overwriting the string in villains with the array returned by split()

Figure 2-18. Overwriting the string in villains with the array returned by split()

Searching with Regular Expressions

Whereas indexOf() returns the index of the first match of a string, search() returns the index of the first match of a RegExp object. So, the following samples are equivalent:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains.indexOf("Goblin");
// 6
villains.search(/Goblin/);
// 6

In the event that you want all matches rather than just the first one, pass match() the RegExp instead. JavaScript will then return an array of matching substrings. Let's find any occurrence of goblin regardless of case in Firebug, verifying our work with Figure 2-19:

var villains = "Green Goblin, Doctor Octopus, Venom, Hobgoblin, and Sandman";
villains.match(/[Gg]oblin/g);
// ["Goblin", "goblin"]

We'll revisit search() and match() in Chapter 5, where you will learn to write more interesting RegExp patterns.

Passing a RegExp object to match()

Figure 2-19. Passing a RegExp object to match()

Explicitly Creating Wrappers

In addition to the members provided by the String(), Number(), or Boolean() constructor functions, wrapper objects receive the following members from Object() too. The only one we'll explore now is valueOf(); the others are covered in Chapter 5.

constructor
hasOwnProperty()
isPrototypeOf()
propertyIsEnumerable()
toLocaleString()
toString()
valueOf()

valueOf() returns the string, number, or boolean associated with a wrapper object. In other words, JavaScript invokes valueOf() on a wrapper to revert it to a string, number, or boolean. So, in Firebug, we can explicitly do what JavaScript does implicitly by creating a wrapper with new and String(), Number(), or Boolean(); querying a member or invoking a method; and then invoking valueOf(). Verify your work with Figure 2-20.

var pre = new String("Hob");
var post = pre.concat("goblin");
pre = pre.valueOf();
pre;
// "Hob"
post;
// "Hobgoblin"
Explicitly converting a string to and from a wrapper object

Figure 2-20. Explicitly converting a string to and from a wrapper object

JavaScript does not immediately revert an explicitly created wrapper to a string, number, or boolean. They provide a way to create a wrapper that persists past a single line of code.

Converting a Value to Another Type

Elastigirl, Mr. Incredible's wife Helen Parr, can reshape any part of her body to be as large as 30 meters or as small as 1 millimeter. For example, in the 2004 Pixar animated film The Incredibles, Elastigirl repeatedly saved the day by reshaping her body into a parachute, rubber raft, and so on. Like Elastigirl, JavaScript values are shape changers, too. They can save the day by changing to another value type, say from a number to a string. Here's how.

Invoking String(), Number(), or Boolean() with the new operator creates a wrapper object. On the other hand, omitting new converts the parameter to a string, number, or boolean. Converting a value to a different type is another thing JavaScript does behind the scenes. So, just as JavaScript quietly converts a string to a wrapper, which is to say to the object type, it also quietly converts a string to the number or boolean type.

You're wondering why would JavaScript ever need to do that for you, aren't you? For one thing, the operators we'll explore typically require their operands to be of a certain type. So, in the event you give them a value of the wrong type to work with, JavaScript saves your bacon by converting it to the correct type. For another, controlling flow with conditional statements, which we'll explore in Chapter 4, relies on JavaScript converting values to the boolean type. In turn, this means that every value you could possibly create has a boolean equivalent. Those that convert to true are referred to as truthy values, while those that convert to false are referred to as falsy values. There are only six falsy values, which are listed here, so all other values convert to true:

undefined
null
false
""
0
NaN

But don't take my word for it. Double-clear Firebug, and then pass each of those in turn to Boolean(), verifying your work with Figure 2-21:

Boolean(undefined);
// false
Boolean(null);
// false
Boolean(false);
// false
Boolean("");
// false
Boolean(0);
// false
Boolean(NaN);
// false
Converting values to the boolean type

Figure 2-21. Converting values to the boolean type

Note

Converting undefined, the value for a missing method or member, to false is the basis for feature testing, which we'll do quite a bit of in the final few chapters.

Every other value converts to true. So, any string except for "", any number except for 0 and NaN, and any object converts to true:

Boolean("Mr. Incredible");
// true
Boolean(["Green Goblin", "Doctor Octopus", "Venom", "Hobgoblin", "Sandman"]);
// true
Boolean(String.fromCharCode);
// true

Converting a Value to a Number

Now let's try converting some values to a number by passing them to Number(). Double-clear Firebug, and then try converting nothing, undefined or null, to a number:

Number(undefined);
// NaN
Number(null);
// 0

Whereas both undefined and null convert to the same boolean (false), they convert to different numbers: undefined to NaN, and null to 0. Note that NaN ("not a number") is a special number literal JavaScript returns for math errors, such as division by 0, or for conversions to the number type that fail. Note too that, if either operand to a math operator like * or - is NaN, the return value will be NaN, too. Therefore, as Figure 2-22 displays, you can do math with null but not with undefined.

var nothing, zilch = null;
nothing * 4;
// NaN
zilch * 4;
// 0
JavaScript can do math with null but not with undefined.

Figure 2-22. JavaScript can do math with null but not with undefined.

Converting strings to numbers is fairly straightforward. Number-like strings such as "4" or "3.33" convert to an equivalent number (4 and 3.33). The "" empty string converts to 0. Everything else converts to NaN. Let's try converting a few strings to a number in Firebug, verifying our work with Figure 2-23:

Number("4");
// 4
Number("");
// 0
Number("Mr. Incredible");
// NaN
Most strings convert to NaN.

Figure 2-23. Most strings convert to NaN.

One common bugaboo is trying to do math with a CSS value; JavaScript represents all of those as strings. So, if you try to move an element 3 pixels to the left by subtracting 3 from a left value of, say, 30px, you're really doing the following calculation. Note that manipulating CSS is covered in Chapter 8.

"30px" - 3;
// NaN

Converting booleans to numbers is very simple. true converts to 1, and false converts to 0. Try doing so in Firebug:

Number(true);
// 1
Number(false);
// 0

Rarely will an object, array, or function convert to a number other than NaN. Trying to do math with an object, array, or function value will generally return NaN to convey failure. Try converting one of each in Firebug, verifying your work with Figure 2-24:

Number(["Green Goblin", "Doctor Octopus", "Sandman"]);
// NaN
Number({hero: "Batman", archenemy: "Joker"});
// NaN
Number(String.fromCharCode);
// NaN
Most object, array, and function values convert to NaN.

Figure 2-24. Most object, array, and function values convert to NaN.

Table 2-1 displays at a glance the number conversions we explored.

Table 2-1. Samples Displaying Spectrum of Conversions to Number Type

Initial Value

Number()

undefined

NaN

null

0

""

0

"30px"

NaN

"4"

4

"3.33"

3.33

true

1

false

0

["Green Goblin", "Doctor Octopus", "Sandman"]

NaN

{hero:"Batman", archenemy: "Joker"}

NaN

String.fromCharCode

NaN

Converting a Value to a String

In Chapter 1, you learned that the [] operator converts a number to a string. So, the following queries both return the member named "3":

"Mezmerella"[2];
// "z"
"Mezmerella"["2"];
// "z"

Though JavaScript frequently converts numbers to strings behind the scenes, occasionally it will have to convert values of other types to strings. Doing so for undefined, null, or booleans is unsurprising:

String(undefined);
// "undefined"
String(null);
// "null"
String(true);
// "true"
String(false);
// "false"

On the other hand, converting values of the object type or array and function subtypes to strings in not straightforward or common. To do so, JavaScript calls the value's toString() method. The following array to string conversions are equivalent:

String(["Green Goblin", "Doctor Octopus", "Sandman"]);
// "Green Goblin,Doctor Octopus,Sandman"
["Green Goblin", "Doctor Octopus", "Sandman"].toString();
// "Green Goblin,Doctor Octopus,Sandman"

So too are the following object to string conversions, as Figure 2-25 displays. Note that the lowercase object indicates the value type, and the uppercase Object indicates the class, which is to say the identifier for the Object() constructor. Figure 2-25 displays the results:

({"Bob Parr": "Mr. Incredible", "Helen Parr": "Elastigirl"}).toString();
// "[object Object]"
String({"Bob Parr": "Mr. Incredible", "Helen Parr": "Elastigirl"});
// "[object Object]"

Don't devote too many brain cells to converting objects, arrays, or functions to strings. It's not important to know.

Converting an array and object to a string

Figure 2-25. Converting an array and object to a string

Methods for Converting a Number to a String

Mr. Incredible's 10-year-old son, Dashiell "Dash" Robert Parr, is a speedster like the Flash. He can probably run at the speed of light: 299,792,458 meters per second. JavaScript numbers may not contain commas, so the number literal for that would be 299792458. That's pretty ugly.

Not to worry. Number wrappers provide the following three methods to convert a bloated number like 299792458 to a succinct string.

Number.toExponential()
Number.toFixed()
Number.toPrecision()

Double-clear Firebug, and let's call each of those in turn on 299792458. First, toExponential() converts a number to an exponential string. Optionally, you can indicate the number of decimal places by passing a number between 0 and 20. Try passing 2 and omitting the parameter, verifying your work with Figure 2-26:

(299792458).toExponential(2);
// "3.00e+8"
(299792458).toExponential();
// "2.99792458e+8"
Converting a number to a string with toExponential()

Figure 2-26. Converting a number to a string with toExponential()

The next method, toFixed(), converts a number to a decimal string. Optionally, you can indicate the number of decimal places by passing a number between 0 and 20. Let's divide 299792458 by 1000 to determine kilometers per second. Then convert that to a string with three or no decimal places, verifying your work with Figure 2-27. Note that omitting the parameter is the same as passing 0.

(299792458 / 1000).toFixed(3);
// "299792.458"
(299792458 / 1000).toFixed();
//"299792"
Converting a number to a string with toFixed()

Figure 2-27. Converting a number to a string with toFixed()

If you are indecisive and want JavaScript to choose between exponential and decimal format, call toPrecision() on the number. The optional parameter differs this time: it's a number between 1 and 21 indicating the number of significant digits. If the parameter is less than the number of digits in the integer part of the number, JavaScript chooses exponential format. If not, JavaScript chooses decimal format. Finally, if you omit the parameter, JavaScript invokes Number.toString(). Try the following samples to clarify how toPrecision() works, verifying your work with Figure 2-28. Note that the final two samples are equivalent.

(299792458).toPrecision(2);
// "3.0e+8"
(299792458).toPrecision(12);
// "299792458.000"
(299792458).toPrecision();
// "299792458"
(299792458).toString();
// "299792458"
Converting a number to a string with toPrecision()

Figure 2-28. Converting a number to a string with toPrecision()

Note that toExponential(), toFixed(), and toPrecision() round trailing digits 0-4 down and 5-9 up just like you would.

Putting Off Learning RegExp Syntax

Even though I will cover RegExp objects more fully in Chapter 5, if you are new to both JavaScript and programming, I suggest simply passing string parameters to the four methods that work with RegExp objects. replace() and split() work with either a string or a RegExp parameter. So, a string will do as is. match() and search() work only with a RegExp parameter, but JavaScript implicitly converts a string parameter to a RegExp object. So, just as a string is converted to a wrapper object by passing it to new and String(), it can be converted to a RegExp object by passing it to new and RegExp(). Insofar as JavaScript does the latter just as quietly as the former, this means that a beginner can put off learning RegExp syntax until after learning JavaScript syntax. I recommend you do.

To illustrate this beginner-friendly JavaScript string to RegExp conversion feature, double-clear Firebug, and then enter and run the following sample. As Figure 2-29 displays, passing a string to match() and search() works just dandy:

var incredibles = "Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack";
incredibles.match("Jack");
// ["Jack"]
incredibles.search("Jack");
// 42
JavaScript quietly converts "Jack" to /Jack/ for both match() and search().

Figure 2-29. JavaScript quietly converts "Jack" to /Jack/ for both match() and search().

JavaScript quietly passed "Jack" to RegExp(), which like String() is referred to as a constructor function. So to explicitly do what JavaScript implicitly did, let's enter and run the following in Firebug. As Figure 2-30 displays, the return values are the same:

var incredibles = "Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack";
incredibles.match(new RegExp("Jack"));
// ["Jack"]
incredibles.search(new RegExp("Jack"));
// 42
Passing a RegExp for a literal string to match() and search()

Figure 2-30. Passing a RegExp for a literal string to match() and search()

Note, however, that, when JavaScript converts a string to a RegExp object, the g, i, and m flags, which we'll explore in Chapter 5, are not set. There's no way for JavaScript to save the day if we intended to pass /jack/ig but instead passed "jack" to match(), as Figure 2-31 displays:

var incredibles = "Mr. Incredible, Elastigirl, Violet, Dash, Jack-Jack";
incredibles.match(/jack/ig);
// ["Jack", "Jack"]
incredibles.match("jack");
// null

Note that match() conveys failure, which is to say no array of matching strings, by returning null. Remember from Chapter 1 that null conveys no value on the heap, in other words, no object, array, or function. That is why match() returned null instead of undefined.

JavaScript does not set the i, g, or m flag when converting a string to a RegExp object.

Figure 2-31. JavaScript does not set the i, g, or m flag when converting a string to a RegExp object.

Summary

In this chapter, you learned that JavaScript converts a string to a wrapper object whenever the string is the left operand to the . or [] operator, quietly passing the string to the String() constructor and then just as quietly reverting the wrapper to a string by invoking its valueOf() method. String wrappers manipulate characters as if they were read-only elements. In other words, string values are immutable, and wrapper methods return a new value without changing the original. So, typically you will want to save the return value or immediately pass it to one of the operators we'll explore in Chapter 3.

Most JavaScript operators are particular about the value type of their operands. Knowing this, JavaScript will save the day by converting an operand of the wrong type to the correct one. Though JavaScript does so behind the scenes, we explored how to do so by passing values to String(), Number(), Boolean(), and Object(). If invoked without the new operator, those constructors convert their argument to a string, number, boolean, or object. So, a string can be converted to a wrapper by passing it to Object() without new or to String() with new:

Object("Spider-Man");
new String("Spider-Man");

So, when JavaScript creates a wrapper for a string, it's really converting the value from the string type to the object type. The same thing goes for number or boolean wrappers, too. Therefore, value type conversion is vital for manipulating values with wrapper methods or with operators. You'll learn more about the latter in Chapter 3. Take a breather, and I'll see you there!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.218.157