Boxing Wrappers

These object wrappers serve a very important purpose. Primitive values don’t have properties or methods, so to access .length or .toString() you need an object wrapper around the value. Thankfully, JS will automatically box (aka wrap) the primitive value to fulfill such accesses.

  1. var a = "abc";
  2. a.length; // 3
  3. a.toUpperCase(); // "ABC"

So, if you’re going to be accessing these properties/methods on your string values regularly, like a i < a.length condition in a for loop for instance, it might seem to make sense to just have the object form of the value from the start, so the JS engine doesn’t need to implicitly create it for you.

But it turns out that’s a bad idea. Browsers long ago performance-optimized the common cases like .length, which means your program will actually go slower if you try to “preoptimize” by directly using the object form (which isn’t on the optimized path).

In general, there’s basically no reason to use the object form directly. It’s better to just let the boxing happen implicitly where necessary. In other words, never do things like new String("abc"), new Number(42), etc — always prefer using the literal primitive values "abc" and 42.

Object Wrapper Gotchas

There are some gotchas with using the object wrappers directly that you should be aware of if you do choose to ever use them.

For example, consider Boolean wrapped values:

  1. var a = new Boolean( false );
  2. if (!a) {
  3. console.log( "Oops" ); // never runs
  4. }

The problem is that you’ve created an object wrapper around the false value, but objects themselves are “truthy” (see Chapter 4), so using the object behaves oppositely to using the underlying false value itself, which is quite contrary to normal expectation.

If you want to manually box a primitive value, you can use the Object(..) function (no new keyword):

  1. var a = "abc";
  2. var b = new String( a );
  3. var c = Object( a );
  4. typeof a; // "string"
  5. typeof b; // "object"
  6. typeof c; // "object"
  7. b instanceof String; // true
  8. c instanceof String; // true
  9. Object.prototype.toString.call( b ); // "[object String]"
  10. Object.prototype.toString.call( c ); // "[object String]"

Again, using the boxed object wrapper directly (like b and c above) is usually discouraged, but there may be some rare occasions you’ll run into where they may be useful.