Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding type coercion in JavaScript

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?

like image 667
Varinder Singh Avatar asked Feb 15 '19 23:02

Varinder Singh


2 Answers

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");
}
like image 106
ZER0 Avatar answered Oct 22 '22 20:10

ZER0


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.

like image 1
John Montgomery Avatar answered Oct 22 '22 18:10

John Montgomery