0

A bug just threw me for a good 45 minute loop scratching my head, when finally I realized assigning an array containing another (empty) array myArray = [[]], holds equivalence with false:

if (myArray == false) {} // true

I realize that if (myArray === false) {} // false but why would an array with length > 0 have equivalence to false at all?

J.Todd
  • 707
  • 1
  • 12
  • 34
  • I think you are confused somehow, empty array, and array with elements evaluate to `true` – thedude May 10 '20 at 07:55
  • 2
    @thedude - They're not confused, the result of `[[]] == false` is indeed `true`. – T.J. Crowder May 10 '20 at 07:56
  • 5
    When you invoke the (myArray == false) you compare values of that myArray object (array is instance of object in javascript) and then myArray.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. – Farista Latuconsina May 10 '20 at 07:57
  • That’s why it’s wise to avoid `==` at all time. – hackape May 10 '20 at 07:59
  • 2
    Does this answer your question? [Empty arrays seem to equal true and false at the same time](https://stackoverflow.com/questions/5491605/empty-arrays-seem-to-equal-true-and-false-at-the-same-time) – Farista Latuconsina May 10 '20 at 07:59
  • @FaristaLatuconsina - **Thank you**, I was going nuts looking for it. Viziionary - You may also be interested in [these bizarre-seeming behaviors](https://stackoverflow.com/questions/9032856/what-is-the-explanation-for-these-bizarre-javascript-behaviours-mentioned-in-the). – T.J. Crowder May 10 '20 at 08:03
  • 1
    @T.J.Crowder woah another interesting discussion bout javascript behaviour which in case i haven't seen it, thank you. – Farista Latuconsina May 10 '20 at 08:10
  • Thank you all for the info and answers and these related questions/answers, all super interesting stuff. – J.Todd May 10 '20 at 08:13

2 Answers2

6

It's because == recursively converts its operands into things it can compare until their types are the same, via the Abstract Equality Comparison operation:

  • In x == y, since y is boolean, it does the result of x == ToNumber(y) (ToNumber).
  • ToNumber(false) is 0, so it does x == 0.
  • Since x is an object and 0 is a number, it does ToPrimitive(x) == 0. (ToPrimitive.)
  • ToPrimitive([[]]) is "" because it ends up doing a join on the array (via Array.prototype.toString), converting the operands to strings. So now we have "" == 0.
  • The algorithm does ToNumber("") == 0. ToNumber("") is 0, so we end up with 0 == 0 which is true.

(When looking at the algorithm in the spec, don't be thrown by the ! in front of some operations like ToNumber. It does not mean negation like it would in JavaScript. It means the operation will never return an abrupt completion. This guide to reading the spec helps with things like that.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

When you call [[]] == false, you compare values of the array and primitive boolean value. So toString() method is called. [[]].toString() is equal to '' so you will compare '' == false and it's true.

wwilkowski
  • 341
  • 4
  • 14