These objects aren’t empty or filled just with the value either, they come with a few things, like prototypes and inherited properties (depending on the type).
Types that aren’t extensible (try running
Object.isExtensible on the variable to see) are commonly mistaken for value types. Extensible types can be assigned properties.
Some of the primitive types (
boolean ) can be created without constructor style creation:
var str = ""; // string var num = 42; // number var bool = false; // boolean
However, the constructor wrapper creation for these variables creates an extensible type:
var str = new String(""); // String var num = new Number(42); // Number var bool = new Boolean(false); // Boolean
Which is why when you try to examine
bool in a REPL environment, you get an object returned.
What really happens when you concatenate:
If the types aren’t a primitive type, they call an function called
ToPrimitive , which is attached to the
Symbol prototype chain.
ToPrimitive calls two publicly accessible functions called
valueOf just returns the value, but
toString is a little more complicated.
There’s some types that inherit the object type, and they’re designed to return
[object Type] in
toString if the type doesn’t have their own implementation.
Quite a few many types inherit the object type:
Most of them have their own
toString implementation, as a decent type should, however you can see the
[object Type] effect by running
Object.prototype.toString.call() over a variable of that type.
let now = new Date(); Object.prototype.toString.call(now); // "[object Date]"
When you concatenate, if
valueOf returns a primitive type, it doesn’t need to call
toString as it can simply concatenate those two values.
If it doesn’t return a primitive type, it will call
toString until it gets a string, and proceed to do a string concatenation with it.
Explaining some idiocy
I’ve seen this image pop up before and it may seem like pure idiocy, but following the above information, it makes sense!
When it calls
dis.call(5) it actually returns a wrapper type variable, instead of a non-wrapper type variable, which makes it extensible, so properties (
wtf ) can be added to the variable.
So while the code can add and change properties,
valueOf still returns the
However, when the increment operator is called, the variable is turned into an normal value type with an updated value.