Home > Articles > Open Source > Ajax & JavaScript

  • Print
  • + Share This
This chapter is from the book

Item 4: Prefer Primitives to Object Wrappers

In addition to objects, JavaScript has five types of primitive values: booleans, numbers, strings, null, and undefined. (Confusingly, the typeof operator reports the type of null as "object", but the ECMA-Script standard describes it as a distinct type.) At the same time, the standard library provides constructors for wrapping booleans, numbers, and strings as objects. You can create a String object that wraps a string value:

var s = new String("hello");

In some ways, a String object behaves similarly to the string value it wraps. You can concatenate it with other values to create strings:

s + " world"; // "hello world"

You can extract its indexed substrings:

s[4]; // "o"

But unlike primitive strings, a String object is a true object:

typeof "hello"; // "string"
typeof s;       // "object"

This is an important difference, because it means that you can’t compare the contents of two distinct String objects using built-in operators:

var s1 = new String("hello");
var s2 = new String("hello");
s1 === s2; // false

Since each String object is a separate object, it is only ever equal to itself. The same is true for the nonstrict equality operator:

s1 == s2; // false

Since these wrappers don’t behave quite right, they don’t serve much of a purpose. The main justification for their existence is their utility methods. JavaScript makes these convenient to use with another implicit coercion: You can extract properties and call methods of a primitive value, and it acts as though you had wrapped the value with its corresponding object type. For example, the String prototype object has a toUpperCase method, which converts a string to uppercase. You can use this method on a primitive string value:

"hello".toUpperCase(); // "HELLO"

A strange consequence of this implicit wrapping is that you can set properties on primitive values with essentially no effect:

"hello".someProperty = 17;
"hello".someProperty; // undefined

Since the implicit wrapping produces a new String object each time it occurs, the update to the first wrapper object has no lasting effect. There’s really no point to setting properties on primitive values, but it’s worth being aware of this behavior. It turns out to be another instance of where JavaScript can hide type errors: If you set properties on what you expect to be an object, but use a primitive value by mistake, your program will simply silently ignore the update and continue. This can easily cause the error to go undetected and make it harder to diagnose.

Things to Remember

  • Object wrappers for primitive types do not have the same behavior as their primitive values when compared for equality.
  • Getting and setting properties on primitives implicitly creates object wrappers.
  • + Share This
  • 🔖 Save To Your Account