Javascript ‘==’ operator and indexOf failure

The other day my collegue, Steve Skrla, was having an infinite recursion issue caused by my javascript clone function. We discovered that the for some reason it was equating a string value with an array value. After a little more digging Steve found the culprit. Simply put, Javascript’s == operator is broken.

I did a little more digging and discovered exactly what Javascript is doing. It turns out that when comparing anything to a string, Javascript first runs a toString on the other item being compared.

[edit]

I should say that this functionality is defined in ECMA script.

From 11.9.3 The Abstract Equality Comparison Algorithm:


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

Even though this functionality is as-designed, I believe it is still a bug. I think both steps 20 and 21 should both return false. This is what most people expect and how other scripting languages work. Please see the comments for more discussion.

[/edit]

Consider the following:

All of the above alerts will output true. Just to go one step further and show that == is inconsistent in its behavior take a look at the following example:

Notice the difference in this example than the previous. I am comparing an array with an object instead of an object with a string. Here, == does a type check and the 2 objects are deemed not equal. == only calls the toString on objects when they are compared with a string.

IndexOf broken

Things can get a little precarious when using indexOf. The good news is that Firefox implements an array indexOf operation that works correctly. The bad news is that IE (at least) doesn’t implement indexOf at all. This means that those of us relying on libraries like JQuery, Prototype, ExtJS …etc have custom implementations of indexOf that look something like this:

Notice the reliance on the == operator. This means that our indexOf’s don’t really work:

The above will output 0 because it equated “Jason” to [[“Jason”]]. This is wrong.

The Fix

While we can’t fix the == we can fix our libraries’ indexOf implementations. All we need to do is use the === (triple equals) operator which does an additional typeof check internally:

Please help get this information out in the wild so library developers can get this fix in.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">