JavaScript – Why Both [] == true and ![] == true Evaluate to False

javascript

I have two statements like this. Why do they both evaluate to false?

console.log([] == true)
console.log(![] == true)

If [] == true is false shouldn't ![] == true result to true?

Best Answer

It's the way coercion works.

The first step of coercion is to convert any non primitive types to primitive types, then using a set of rules convert the left, right or both sides to the same type. You can find these rules here.

In your case [] == true, would pass through these 4 steps:

  1. [] == true
  2. [] == 1
  3. "" == 1
  4. 0 == 1

Whereas based on operator precedence the ! in ![] == true is executed first so the expression is converted to false == true which is obviously false.

You can try the live demo by Felix Kling to better understand how the sameness operator works.

In more words:

The value ![] is false, because [] is an Object (arrays are objects) and all objects, not including null, are truthy. So any array, even if it is empty will always be a truthy, and the opposite of a truthy is always false. The easiest way to check if a value is a truthy is by using !!.

console.log("![]: " + ![]);
console.log("!![]: " + !![]);

When you are using a loose comparison (using == instead of ===) you are asking the JavaScript engine to first convert the values into the same type and then compare them. So what happens is the values get converted according to a set of rules, once they are the same type, they get compared though the same process as a strict equality check (===). The first change that [] goes through is to get converted to a string, the string version of an empty array is an empty string "", the empty string is then converted to a number, the numeric value of an empty string is 0, since the numeric value of true is 1 and 0 != 1, the final output is false.

console.log("[] == true => `" + ([] == true) + "`");

console.log("String([]) => `" + String([]) + "`");
console.log("Number('') => `" + Number("") + "`");

console.log("Number(true) => `" + Number(true) + "`");