Xavi Xavi - 4 months ago 15
Javascript Question

Why does 2 == [2] in JavaScript?

I recently discovered that

2 == [2]
in JavaScript. As it turns out, this quirk has a couple of interesting consequences:

var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true


Similarly, the following works:

var a = { "abc" : 1 };
a[["abc"]] === a["abc"]; // this is also true


Even stranger still, this works as well:

[[[[[[[2]]]]]]] == 2; // this is true too! WTF?


These behaviors seem consistent across all browsers.

Any idea why this is a language feature?

EDIT: Here are more insane consequences of this "feature":

[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!

var a = [0];
a == a // true
a == !a // also true, WTF?


These examples were found by jimbojw of trephine and http://jimbojw.com fame as well as walkingeyerobot.

Answer

You can look up the comparison algorithm in the ECMA-spec (relevant sections of ECMA-262, 3rd edition for your problem: 11.9.3, 9.1, 8.6.2.6).

If you translate the involved abstract algorithms back to JS, what happens when evaluating 2 == [2] is basically this:

2 === Number([2].valueOf().toString())

where valueOf() for arrays returns the array itself and the string-representation of a one-element array is the string representation of the single element.

This also explains the third example as [[[[[[[2]]]]]]].toString() is still just the string 2.

As you can see, there's quite a lot of behind-the-scene magic involved, which is why I generally only use the strict equality operator ===.

The first and second example are easier to follow as property names are always strings, so

a[[2]]

is equivalent to

a[[2].toString()]

which is just

a["2"]

Keep in mind that even numeric keys are treated as property names (ie strings) before any array-magic happens.

Comments