I know ==
operator performs the type coercion. But I can't understand the below behaviour.
const x = new Boolean(false);
if (x) {
console.log("if(x) is true");
}
if (x == false) {
console.log("if(x == false) is true");
}
Surprisingly, above snippet prints both lines:
if(x) is true
if(x == false) is true
Can someone explain this weird behaviour or there is something fundamental I'm missing?
As mentioned by other answers, that's because x
is an Object – a Boolean object, but still an object, since you're using the new
operator – and is coerced only when you compare x
to false
: the if (x)
is checking if x
is a truthy value, and therefore doesn't need coercion (there are no other operands involved): an object is always "true" (weeeell… almost always: typeof null
returns object
but it's a falsy value. But that's another story…).
You can easily checking when the coercion is invoked tapping the toPrimitive symbol:
var x = new Boolean(false);
// first of all, if it wasn't an object you couldn't
// do this
x[Symbol.toPrimitive] = function(hint) {
console.log({hint});
return this.valueOf();
}
// no console.log yet
if (x) {
console.log("if(x) is true");
}
// here you got the console.log before the one
// inside the block, since the coercion happens
// in the `if`
if (x == false) {
console.log("if(x == false) is true");
}
new Boolean(false)
produces an object. Objects are always truthy even if they wrap a falsy primitive value. For example, new String("")
is also truthy despite ""
being falsy.
On the other hand, when you do new Boolean(false) == false
, it coerces the object to its primitive value for the comparison. Incidentally, new Boolean(false) === false
is not true, since their types don't match.
As a general rule, you shouldn't use object constructors for primitive types unless you have a specific reason for it, to avoid unexpected behavior like this.
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