JavaScript has boxed primitive types so that their instances can inherit properties (especially methods) from their prototypes, which fits in well with the auto-boxing of the receiver value on property access (and method calls).
For example
Boolean.prototype.demo = "!";
console.log(true.demo);
console.log(true.toString());
Contrast this to undefined.toString()
, which is not auto-boxed.
This reason is confirmed by the creator of the language:
the so-called primitive types Boolean, Number, and String each have a
corresponding Object subtype: Boolean, Number, and String
respectively. When a primitive value is used as an object, it is
automatically “boxed” or wrapped by a new instance of the
corresponding object subtype. When used in an appropriate primitive
type context, the box/wrapper converts back to the primitive value.
However, he actually was rather unhappy with that, and wanted to change the type system for ES4 (which, we all known, never happened).
The question could actually even have been framed the other way round: "Why does JavaScript have primitive types when it already has Boolean
, Number
and String
objects?". They really aren't necessary at all, many languages do fine without them and just live the object-oriented everything is an object maxim - including languages that were the inspirations for JS.
Again, we learn from Brendan Eich:
The diktat from upper engineering management was that the language must
“look like Java”. […]
I’m not proud, but I’m happy that I chose Scheme-ish first-class
functions and Self-ish (albeit singular) prototypes as the main
ingredients. The Java influences, especially y2k Date bugs but also
the primitive vs. object distinction (e.g., string
vs. String
), were
unfortunate.