I know sometimes JS might make you want to punch someone. At least figuratively.

However, that is not the type of boxing this article's title is referring to. The type of boxing in question here is the concept of wrapping a primitive non-object with a corresponding wrapper object.

Contrary to common belief, primitive data types in Javascript are not objects. They have no methods and no properties, but they do have corresponding objects (except for null and undefined) that provide them.

But if primitives have no methods and are not objects then how does this work:


Lets do some introspection of "foo" and see what clues we might find.

"foo".constructor === String;
// true

"foo".__proto__ === String.prototype;
// true

"foo" instanceof String;
// false

typeof "foo";  
// "string"

new String("foo") instanceof String;  
// true

typeof new String("foo");  
// "object"

We clearly have two different types of data here:

  • "foo" which is a string
  • new String("foo") which is an object

The latter is the only one that is an instance of String. It is also the only one with a constructor of String. So then what is happening?

When you try to access a property on a primitive value, behind the scenes that primitive value gets automatically boxed into (or wrapped by) it's corresponding object.

It's important to understand that the wrapper object is ephemeral. Consider:

var objectStr = new String("foo");  
objectStr.bar = 2;  
// 2

var primitiveStr = "foo";  
primitiveStr.bar = 2;  
// undefined

As you can see, objects can have properties but primitives cannot. However though, when you try to set a property on a primitive it gets boxed into an object, so that object gets the property set. Then when you try to read that property, you are reading from the primitive which gets boxed again (with a new object) so the property is no longer there. This also may help explain why primitives in Javascript are immutable.

At this point you might be thinking that this explains why you cannot call methods directly on number literals:

5.toString(); // SyntaxError: Unexpected token ILLEGAL  

One might assume that this means primitive numbers simply do not get autoboxed. This has nothing to do with boxing though. As you can see, if you reference the number using an identifier it boxes just fine:

var five = 5;  
typeof five; // "number"  
five.toString(); // "5"  

What is actually happening here is that when you put a dot after a number literal in Javascript it is expecting a decimal (e.g. 5.23). You can get around this with (5).toString()

Lastly, you can manually box and unbox values by casting primitives to an Object and invoking valueOf on wrapper objects, respectively:

var primitiveStr = "foo";  
var objectStr = Object(primitiveStr);

var objectNum = new Number(5);  
var primitiveNum = objectNum.valueOf();  

© 2017. All Rights Reserved.

Proudly published with Ghost