Three special reference types are designed to ease interaction with primitive values:
These types can act like the other reference types.
They also have a special behavior related to their primitive-type equivalents.
Every time a primitive value is read, an object of the corresponding primitive wrapper type is created behind the scenes.
In this way we can access its member methods for manipulating the data.
Consider the following example:
let s1 = "test"; let s2 = s1.substring(2);
In this code, s1 is a variable containing a string, which is a primitive value.
On the next line, the substring()
method is called on s1 and stored in s2.
Primitive values aren't objects, so they shouldn't have methods.
Behind the scenes, when s1 is accessed in the second line, it is being accessed in read mode.
Any time a string value is accessed in read mode, the following three steps occur:
Javascript does the following behind the scenes.
let s1 = new String("some text"); let s2 = s1.substring(2); s1 = null;
This behavior allows the primitive string value to act like an object.
These same three steps are repeated for Boolean and numeric values using the Boolean and Number types, respectively.
The properties and methods cannot be added at runtime for primitive types.
let s1 = "some text"; s1.color = "red"; console.log(s1.color); // undefined
Here, the second line attempts to add a color property to the string s1.
However, when s1 is accessed on the third line, the color property is gone.
This happens because the String object that was created in the second line is destroyed by the time the third line is executed.
The third line creates its own String object, which doesn't have the color property.
The Object
constructor acts as a factory method and returns an instance of a primitive wrapper based on the type of value passed into the constructor.
For example:
let obj = new Object("some text"); console.log(obj instanceof String); // true
When a string is passed into the Object constructor, an instance of String is created.
A number argument results in an instance of Number.
A Boolean argument returns an instance of Boolean.
Calling a primitive wrapper constructor using new is not the same as calling the casting function of the same name.
let value = "25"; let number = Number(value); // casting function console.log(typeof number); // "number" let obj = new Number(value); // constructor console.log(typeof obj); // "object"
In this example, the variable number is filled with a primitive number value of 25 while the variable obj is filled with an instance of Number.