19

I would like to know why the expression given in the title

[] == ![]

is evaluated to true.

You cannot compare arrays as strings. I get that. If

[] == []

will evaluate to false because the references are different. Though if we have the following statement.

var arr = []; 
arr == arr // this evaluates to true simply because references are the same.

In order A == B to return true either A and B have to be false or true. A == !B in order to return true A can be true and B can be false or vice versa but in this case, A and B are the same values so I don't get it.

Hardik Shah
  • 3,241
  • 2
  • 17
  • 36
Tek
  • 1,088
  • 11
  • 21
  • http://stackoverflow.com/a/9550412/19068 has a whole list of questions asking why X == Y (or != Y). – Quentin Jul 29 '16 at 15:33
  • Note from [the tour](http://stackoverflow.com/tour): *Focus on questions about an actual problem you have faced.* – Quentin Jul 29 '16 at 15:34

5 Answers5

22

Basically Javascript tries to convert both the sides into Number if both the types are not same. And if its an Object, It tries to convert into primitive value

So in this case step by step will be

=> []==![]

=> []==false // Type conversion by the statement itself

=> []==0 // To number of right operand

=> ""==0 // To Primitive call for Array which will in this case convert to empty string

=> 0==0 // To number call of "" which is 0

=> true

One can check for the ecmascript explanation here in the compiler description http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

Akarsh Satija
  • 1,600
  • 20
  • 28
12

Whenever 2 values are compared using == , javascript performs the Abstract Equality Comparison Algorithm.

enter image description here

Here, x is [], and y is ![]. Also,

typeof([]) // "object"
typeof(![]) // "boolean"

Since y is a boolean and x is an object, condition 7 is the first to hold:

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

What’s the value of ToNumber(y)?

Number(![]) // 0

because [] is a truthy value, negating makes it false. Number(false) is 0

Now we have the comparison: [] == 0.

Since typeof(0) is "number", condition 8 now holds:

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

ToPrimitve(x) is like x.toString().

[].toString() // ”” - the empty string

Almost done we now face with the comparison: “” == 0

Now, condition 5 holds:

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

ToNumber(“”) // 0

Finally both operands have the same type and condition 1 holds. I think you can take if from here :)

read about Abstract Equality Comparison on the specs!

Bar Horing Amir
  • 3,302
  • 2
  • 20
  • 19
10

![] evaluates to false because the reference is truthy. [] can be converted to an number (0 in this case) which is falsey. Therefore: the condition passes as equal. If you did === it would be false.

Daniel A. White
  • 174,715
  • 42
  • 343
  • 413
  • _“Because the reference is truthy”_ — a reference isn’t truthy or not truthy, a _value_ is. _“Therefore: the condition passes as equal”_ — it doesn’t pass as equal because something falsy is compared with `false` using abstract comparison (or else `NaN == false`, `null == false`, etc. would be `true`); you’re missing the type coercion for `false`. Step by step, `[]` is coerced to `""`, then to `0`, then `false` is coerced to `0`, then strict equality comparison is used as `0 === 0`, resulting in `true`. – Sebastian Simon Aug 26 '19 at 03:39
  • This should not be the chose answer, as it does not detail the implicit type coercion happening on both sides of the equality operator, as explained by both @AkarshSatija and SebastianSimon. – Derek Henderson Oct 02 '19 at 19:37
3

Here is a more detail explanation from codementor.io

Before understanding what is happening , we need to understand the concept of truthy and falsy in JavaScript and how the ! (logical NOT) operator works. Values such as false, null, undefined, NaN, 0, '' and "" are considered as falsy. Other values like *true, {}, [], "foo"* etc. are considered truthy. The ! operator, on the other hand, is defined for boolean values only. Any other data type will automatically be coerced into it's corresponding boolean value when operated with ! operator. Here, ![] evaluates to false and the comparison actually becomes '[] == false' which evaluates to 'true'. Isn't that supposed to be false, since empty arrays are truthy? That's right but the double equal operator evaluates expressions on certain rules. We're trying to compare an object with a boolean value and JavaScript will implicitly convert the operands to Number type. Number([]) is 0 and Number(false) is also 0, which evaluates to true since zero is equal to zero

Johnny
  • 2,202
  • 6
  • 19
  • 21
1

Your Understanding is correct but you have missed that ! operator is asking for explicit coercion of empty array to Boolean.

Steps in [] == ![]

  1. Explicit Coercion right side expression to Boolean by ! operator. So , ![] becomes false.
  2. Now action of == operator. Since one of them is Boolean ( false on right side of == operator). which will coerced to Number.
  3. Where as [] will be coerced to Number which 0.

So 0 == 0 , which is true.

Nikhil_k
  • 31
  • 2