8

In JavaScript, I noticed that []==![] result is true. demo

I don't understand this result. Can you explain why?

pimvdb
  • 151,816
  • 78
  • 307
  • 352
Koerr
  • 15,215
  • 28
  • 78
  • 108
  • 2
    @zengr: I don't know. That looks like a completely different question to me. – BoltClock Oct 13 '12 at 08:22
  • 1
    @BoltClock: [] in boolean context is true and ![] is thus false, after that the code is doing [] == false, which results in true. – Antti Haapala -- Слава Україні Oct 13 '12 at 08:25
  • @AnttiHaapala: That's not fully correct - `[1]` is true in boolean context, yet `![1]` is false and `[1] == false` also yields false. It's not the boolean context but the `==` algorithm. – pimvdb Oct 13 '12 at 08:28
  • @BoltClock I agree with @Antti. The answer describes in detail about the conversion of `[]` and `![]`, which answers this question. – zengr Oct 13 '12 at 08:28
  • 2
    @zengr: That doesn't make it the same question. – BoltClock Oct 13 '12 at 08:35
  • @pimvdb I was only pointing out that `[] == ![]` is equivalent to `[] == false` (the `![]` evaluating to `false` should be trivial), and all interesting things that happen after that should already have been covered in all prior questions & answers. There is not much point in allowing yet another question-answer thread for questions like "why `[] != !'a'` is false?". – Antti Haapala -- Слава Україні Oct 13 '12 at 09:10
  • Not to be confused with [`[] !== []`](http://stackoverflow.com/q/13757109/1529630) – Oriol Aug 14 '16 at 20:30

1 Answers1

10

[] is an array, but ![] is a boolean value. Whenever you try to compare two objects with different types with == both objects should be transformed into comparable objects (using ToNumber, see step 7. in 11.9.3). This is why [] == ![] yields true, the first empty array gets evaluated to false.

11.9.3 The Abstract Equality Comparison Algorithm

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. [...]
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  8. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

However, if you use the strict type comparison operator === the result is false, since both types differ:

11.9.6 The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Undefined, return true.
  3. If Type(x) is Null, return true.
  4. If Type(x) is Number, then
    1. If x is NaN, return false.
    2. If y is NaN, return false.
    3. If x is the same Number value as y, return true.
    4. If x is +0 and y is -0, return true.
    5. If x is -0 and y is +0, return true.
    6. Return false.
  5. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
  6. If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
  7. Return true if x and y refer to the same object. Otherwise, return false.
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • Please elaborate "transformed into comparable objects. This is why [] == ![] yields true". This answer looks like speculation without proof. RE: Edit: Still insufficient. The relevant part is section 11.9.3. You could follow the defined steps to get to the right conclusion. – Rob W Oct 13 '12 at 08:23
  • @RobW: I noticed my error and removed the wrong equality operator. Took me a little while to load ECMA-262.pdf, my connection is slow as BASIC. – Zeta Oct 13 '12 at 08:29
  • @RobW: Thanks bookmarked it. I also saved a copy on my HDD, this should come in handy – Zeta Oct 13 '12 at 08:31
  • 1
    What is happening with `[]==![]` is an abstract equality comparison between `[]` and `![]` Note that `typeof(![])` is `boolean` and `typeof([])` is `object`. From the documentation For x == y, If Type(y) is Boolean, return the result of the comparison x == ToNumber(y). ToNumber of `![]` that is `false` is 0 So, it comes down to [] == 0 and the result of `[]==0` is `true` – Jacob George Oct 13 '12 at 08:41
  • @kidmenot: Apparently it's still way too early on a Saturday morning. Fixed my answer. – Zeta Oct 13 '12 at 08:45
  • One thing to note is that the array is first converted to string by ToPrimitive, thus `[]`, `[ "" ]`, `[ null ]`, and `[ undefined ]` still become `''`, and `'' == 0` is `true`. But `[ "", "" ]` becomes `","` and `"," == 0` is `false`, because `ToNumber(',')` evaluates to `NaN`. – Antti Haapala -- Слава Україні Oct 13 '12 at 08:53