Empty arrays seem to equal true and false at the same time
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 if (arr == false)
you compare values of this object and the primitive false
value. Internally, arr.toString()
is called, which returns an empty string ""
.
This is because toString
called on Array returns Array.join()
, and empty string is one of falsy values in JavaScript.
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 false
is coerced to 0
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 0
== 0
, which is true
.
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 ToNumber(false)
is 0
, so we now have:
[] == 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 ToPrimitive([])
is the empty string, so we now have:
"" == 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 ToNumber("")
is 0
, which leaves us with:
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)