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.
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"
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"
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";
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
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()
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.
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"
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"
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"
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
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"
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() // "İ"
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!
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
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
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
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"
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.
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"
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"
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"]
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"]
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"
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"
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.
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"
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.
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 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
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
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
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
Table 2-1 displays at a glance the number conversions we explored.
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.
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"
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"
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"
Note that toExponential(), toFixed()
, and toPrecision()
round trailing digits 0-4 down and 5-9 up just like you would.
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 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
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
.
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!
18.188.218.157