When we introduced strings earlier in this chapter, we pointed out a strange feature of that data type: to operate on strings, we use object notation. For example, a typical operation involving strings might be the following:
s = "These are the times that try people's souls."; last_word = s.substring(s.lastIndexOf(" ")+1, s.length);
In Chapter 6, Functions, we'll see something similar: functions also have properties that we can access using object notation. What's going on? Are strings and functions objects, or are they distinct data types? In Navigator 3.0, the typeof operator assures us that strings have a data type "string" and that functions are of type "function" and that neither is of type "object". Why then, do they use object notation?
The truth is that each primitive data type (i.e., the data types that are not objects or arrays) has a corresponding object type defined for it. That is, besides supporting the number, string, boolean and function data types, JavaScript also supports Number, String, Boolean, and Function object types. These object types are "wrappers" around the primitive data types--they contain the same primitive data value, but also define the properties and methods that we use to manipulate that data (or to manipulate strings and functions, at least; the Number and Boolean objects are not as useful as the String and Function objects.)
As an untyped language, JavaScript can very 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, and 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 object wrappers; we just don't use the other types in an object context nearly as often as we use strings in that context.
When we use a string in an object context, note that the String object that is created is a transient one--it is used to allow us to access a property or method, and then it is no longer needed and is reclaimed by the system. Suppose s is a string, and we determine the length of the string with a line like this:
len = s.length;
If for some reason we want to use a String object explicitly in our program, we will have to create a non-transient one that will not be automatically discarded by the system. We create String objects just as we create other objects, with the new operator. (The new operator will be introduced in Chapter 4, Expressions and Operators, and we'll learn more about object creation in Chapter 7, Objects.) For example:
s = "hello world"; // a primitive string value S = new String("Hello World"); // a String object
Once we have created a String object S, what can we do with it? Nothing that we can't do with the corresponding primitive string value. If we use the typeof operator, it will tell us that S is indeed an object, and not a string value, but except for that case, we'll find that we can't distinguish between the a primitive string and the String object. This is for two reasons. First, as we've seen, strings are automatically converted to String objects whenever necessary. But it turns out that the reverse is also true. Whenever we use a String object where a primitive string value is expected, JavaScript will automatically convert the String to a string. So if we use our String object with the + operator, a transient primitive string value will be created so that the string concatenation operation can be performed:
msg = S + '!';
Bear in mind that everything we've said in this section about string values and String objects applies also to the other primitive types and their corresponding Number, Boolean, and Function objects. You can learn more about these object types from their respective entries in the reference section of this book. In Chapter 9, Further Topics in JavaScript we'll see more about this primitive type/object duality, and about automatic data conversion in JavaScript.