3.12 Primitive Data Type Wrapper Objects
When we discussed strings earlier in
this chapter, I pointed out a strange feature of that data type: to
operate on strings, you use object notation. For example, a typical
operation involving strings might look like the following:
var s = "These are the times that try people's souls.";
var last_word = s.substring(s.lastIndexOf(" ")+1, s.length);
If you didn't know better, it would appear that
s was an object and that you were invoking methods
and reading property values of that object.
What's going on? Are strings objects, or are they primitive
data types? The typeof operator (see Chapter 5) assures us that strings have the data type
"string", which is distinct from the data type
"object". Why, then, are strings manipulated using object
notation?
The truth is that a corresponding object class is defined for each of
the three key primitive data types. That is, besides supporting the
number, string, and
boolean data types, JavaScript also supports Number, String, and
Boolean classes. These classes are wrappers around the primitive data
types. A wrapper contains the same primitive
data value, but it also defines properties and methods that can be
used to manipulate that data.
JavaScript can flexibly convert values from one type to
another. When we use a string in an object context -- i.e., when
we try to access a property or method of the string -- JavaScript
internally creates a String wrapper object for the string value. This
String object is used in place of the primitive string value; the
object has properties and methods defined, so the use of the
primitive value in an object context succeeds. The same is true, of
course, for the other primitive types and their corresponding wrapper
objects; we just don't use the other types in an object context
nearly as often as we use strings in that context.
Note that the String object created when we use a string in an object
context is a transient one -- it is used to allow us to access a
property or method and then is no longer needed, so it is reclaimed
by the system. Suppose s is a string and we
determine the length of the string with a line like this:
var len = s.length;
In this case, s remains a string; the original
string value itself is not changed. A new transient String object is
created, which allows us to access the length
property, and then the transient object is discarded, with no change
to the original value s. If you think this scheme
sounds elegant and bizarrely complex at the same time, you are right.
Typically, however, JavaScript implementations perform this internal
conversion very efficiently, and it is not something you should worry
about.
If we want to
use a String object explicitly in our program, we have to create a
nontransient one that is not automatically discarded by the system.
String objects are created just like other objects, with the
new operator. For example:
var s = "hello world"; // A primitive string value
var S = new String("Hello World"); // A String object
Once we've created a String object S, what
can we do with it? Nothing that we cannot do with the corresponding
primitive string value. If we use the
typeof operator, it tells us that
S is indeed an object, and not a string value, but
except for that case, we'll find that we can't normally
distinguish between a primitive string and the String
object.[6] As we've already
seen, strings are automatically converted to String objects whenever
necessary. It turns out that the reverse is also true. Whenever we
use a String object where a primitive string value is expected,
JavaScript automatically converts the String to a string. So if we
use our String object with the
+ operator, a transient primitive
string value is created so that the string concatenation operation
can be performed:
[6] Note, however, that the eval(
) method treats string values and
String objects differently, and it will not behave as you expect it
to if you inadvertently pass it a String object instead of a
primitive string value. msg = S + '!';
Bear in mind that everything we've discussed in this section
about string values and String objects applies also to number and
boolean values and their corresponding Number and Boolean objects.
You can learn more about these classes from their respective entries
in the core reference section of this book. In Chapter 11, we'll see more about this primitive
type/object duality and about automatic data conversion in
JavaScript.