Empty arrays seem to equal true and false at the same time

2022-08-30 00:56:32

Empty arrays are true but they're also equal to false.

var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");

I guess this is due to the implicit conversion operated by the equality operator.

Can anyone explain what's going on behind the scenes?


答案 1

You're testing different things here.

if (arr) called on object (Array is instance of Object in JS) will check if the object is present, and returns true/false.

When you call you compare values of this object and the primitive value. Internally, is called, which returns an empty string . if (arr == false)falsearr.toString()""

This is because called on Array returns , and empty string is one of falsy values in JavaScript.toStringArray.join()


答案 2

Regarding the line:

if (arr == false) console.log("It's false!");

Maybe these will help:

console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true

What I believe is happening is that the boolean is coerced to for comparison with an object (the left-hand side). The object is coerced to a string (the empty string). Then, the empty string is coerced into a number, as well, namely zero. And so the final comparison is == , which is .false000true

Edit: See this section of the spec for details on exactly how this works.

Here's what's happening, starting at rule #1:

1. If Type(x) is different from Type(y), go to step 14.

The next rule that applies is #19:

19. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

The result of is , so we now have:ToNumber(false)0

[] == 0

Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #21:

21. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x)== y.

The result of is the empty string, so we now have:ToPrimitive([])

"" == 0

Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #17:

17. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x)== y.

The result of is , which leaves us with:ToNumber("")0

0 == 0

Now, both values have the same type, so the steps continue from #1 until #7, which says:

7. If x is the same number value as y, return true.

So, we return .true

In brief:

ToNumber(ToPrimitive([])) == ToNumber(false)