Boolean(new Boolean(...)) === true because new Boolean(...) is an object.
But why Number(new Boolean(false)) === 0 (+new Boolean(false) === 0) and Number(new Boolean(true)) === 1? Why not NaN*?
Why in the first example there is no unboxing, but in the second case there is it?
*isNaN(Number({})) === true
As @ASDFGerte mentioned. This is because the ToNumber() method which is called by the Number() constructor will call .ToPrimitive() on the argument if an object is passed. This is why it's treated as a Boolean primitive rather than an object.
isNaN(Number({})) === true
While this is correct, I think you're equating an object with a Boolean object and the two are not equivalent.
Let's start from the most important thing - Number converts the argument its given into a numeric. However, it doesn't arbitrarily do that - there are rules about numeric conversion and when it comes to objects, it's not as simple as "all objects are NaN". Consider this:
const obj0 = {}
const obj1 = {
toString() {
return 1;
}
}
const obj2 = {
toString() {
return 1;
},
valueOf() {
return 2;
}
}
const obj3 = {
toString() {
return 1;
},
valueOf() {
return 2;
},
[Symbol.toPrimitive]() {
return 3;
}
}
const obj4 = Object.create(null);
console.log(Number(obj0)); //NaN
console.log(Number(obj1)); //1
console.log(Number(obj2)); //2
console.log(Number(obj3)); //3
console.log(Number(obj4)); //Error
Not all objects are equal when converting to a number. Some happen to be even more unequal than others.
When Number is given an object, it goes through the process to convert it to a primitive with a preference (hint) for a number. To do this, it will go through the following steps:
@@toPrimitive method.
valueOf method.
valueOf will be checked first.toString method
Once an appropriate method has been found, it's executed and the value returned will be transformed into numeric.
We haven't touched Boolean yet - this is just how the generic Number does the conversion. So, in summary - an object can be converted to a primitive number, if it implements the correct functionality to do so.
Boolean objects do implement the correct functionality - they have a valueOf method that returns the primitive boolean they hold:
const T1 = new Boolean(true);
const T2 = new Boolean(true);
console.log("T1.valueOf()", T1.valueOf());
console.log("typeof T1.valueOf()", typeof T1.valueOf());
console.log("T1 === T2", T1 === T2);
console.log("T1.valueOf() === T2.valueOf()", T1.valueOf() === T2.valueOf());
So, in that case:
Number(new Boolean(true)) = Number(new Boolean(true).valueOf()) = Number(true)
And if we generalise it a bit, then: Number(new Boolean(bool)) = Number(bool)
From the ToNumber conversion we know that true is turned into 1 while false is turned into 0. Thus the equality Number(new Boolean(false)) === 0 makes perfect sense, since Number(false) is indeed 0. Same with Number(new Boolean(true)) === 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With