Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If both [0] == 0 and 0 == [[0]] are true than why is [0] == [[0]] false?

Tags:

javascript

We all know javascript does funky conversions when testing for equality, but what exactly happens under the hood?

> [0] == 0
true
> 0 == [[0]]
true
> [0] == [[0]]
false

Yes, it was naive of me to expect transitivity from == operator.

like image 972
Luboš Turek Avatar asked Dec 30 '14 10:12

Luboš Turek


3 Answers

[0] == 0 and 0 == [[0]] compares a primitive value with an object and thus type conversion will be performed. In both cases [0] and [[0]] will eventually be converted to the primitive value 0.

This is defined in steps 8 (and 9) of the The Abstract Equality Comparison Algorithm:

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

However, [0] === [[0]] compares two objects and two different objects are never equal to each other:

1f. Return true if x and y refer to the same object. Otherwise, return false.


Here is a slightly simper example that demonstrates that loose comparison is not transitive:

" " == 0 // true
"\n" == 0 // true
" " == "\n" // false

The first two comparisons perform type conversion (string to number), the last one does not and the values of both strings are different.

like image 174
Felix Kling Avatar answered Oct 07 '22 08:10

Felix Kling


Your first 2 examples implicitly converts the arrays to strings, then compares those to the 0:

var a = [0].toString(); // "0"
var b = a == 0 // "0" == 0; // true

The last example doesn't cast the arrays, it just compares the arrays' identities. These don't match, obviously, so false is returned.

The extra layer of depth you have in some of those arrays doesn't make a difference, in your examples:

[0] == [0]     // false, they're not the same array.
0 == [[[[0]]]] // true, [[[[0]]]].toString() === "0", "0" == 0

As @JanDvorak mentioned in a comment on @KooiInc's answer, behind the scenes, JS doesn't use toString for this conversion. However, in concept this is what's happening.

like image 26
Cerbrus Avatar answered Oct 07 '22 08:10

Cerbrus


The behaviour is as per JavaScript The Abstract Equality Comparison Algorithm

  1. Comparing [0] == 0 - Operand types are different

Matches Case 9 of algo: Type(x) is Object and Type(y) is either String or Number
result: ToPrimitive(x) == y. i.e '0' == 0, hence true

  1. Comparing 0 == [[0]] - Operand types are different

Matches Case 8 of algo: If Type(x) is either String or Number and Type(y) is Object, result: x == ToPrimitive(y). i.e 0 == '0', hence true

  1. Comparing [0] == [[0]] - Operand types are same i.e object

Matches Case 1 of algo: Type(x) is the same as Type(y), if type is 'object' Return true if x and y refer to the same object. Otherwise, return false. i.e reference will be matched, hence false

like image 1
Amitesh Avatar answered Oct 07 '22 07:10

Amitesh