This blog post is first of a series:
What are wrapper objects for primitive values?
Why you shouldn’t change built-in prototypes [coming soon]
How do primitive values get their properties? [coming soon]
Each of the primitive types boolean, number, bigint, string and symbol has an associated wrapper class (Boolean, Number, BigInt, String, Symbol). In this blog post, we examine what these classes are good for.
Table of contents:
Wrapper classes for primitive types
Recall that these are all primitive values:
undefined
null
booleans
numbers
bigints
strings
symbols
Each primitive type (except for the types of undefined and null) has a corresponding wrapper class:
Boolean
Number
BigInt
String
Symbol
The key purpose of these classes is to provide properties (mostly methods) for primitive values. We’ll see how exactly that works in the third of this series of blog posts. This is an example:
> 'ab'.toUpperCase === String.prototype.toUpperCase
true
Each wrapper class can also be invoked in two ways:
It can be invoked via new, which creates a new instance. Doing this (explicitly) is almost never useful for programmers.
It can be function-called, which converts an arbitrary value to the primitive type that the class represents. This is the way for converting to primitive types that I recommend.
Instantiating wrapper classes
We create instances of wrapper classes via new:
> new String('ab') instanceof String
true
That is, new String() wraps a primitive string and produces a wrapper object.
Primitive values vs. wrapper objects
Interestingly, the primitive value 'ab' is not an instance of String:
> 'ab' instanceof String
false
typeof also shows us the 'ab' is primitive, but new String('ab') is an object:
> typeof 'ab'
'string'
> typeof new String('ab')
'object'
That is, the values of a primitive type are different from the instances of the associated wrapper class. In day-to-day programming, I usually pretend that wrapper objects don’t exist. They are used under the hood but rarely useful elsewhere.
For more information on the differences between primitive values and objects, see “JavaScript for impatient programmers”.
Generically wrapping primitive values
In addition to wrapping a primitive value by new-invoking a wrapper class, we can also do so generically by function-calling Object (the class of most objects):
assert.equal(
Object('ab') instanceof String, true
);
assert.equal(
Object(123) instanceof Number, true
);
As an aside, if the argument of Object() is an object, it is simply returned without any changes:
const obj = {};
assert.equal(
Object(obj), obj
);
Unwrapping primitive values
The generic way of unwrapping a wrapper object is method .valueOf():
> new String('ab').valueOf()
'ab'
> new Number(123).valueOf()
123
Function-calling wrapper classes
Function-calling wrapper classes provides us with a descriptive way of converting arbitrary values to primitives:
> Boolean(0)
false
> Number('123')
123
> String(123)
'123'
These functions also unwrap where possible:
> Number(new Number(123))
123
> Number(Object(123))
123
Further reading
Read More