The <=
operator will coerce its operands to try to make them comparable. The full details are in the specification's Abstract Relational Comparison operation, but basically:
When you compare an object reference with a primitive, it tries to convert the referenced object to a primitive. In this case, since the primitive is a number, it will try to get a primitive number from the object if the object supports that (arrays don't) and then fall back on getting a string. At which point it has a string and a number, so it coerces the string to number and compares them numerically.
When you convert an array to a string, it does the same thing join
does: Joins the string version of all the entries together separated by commas. Of course, if you have only one entry, you'll end up with just that entry (as a string).
Here's a simpler example:
var a = [2];
console.log(a < 10); // true
The steps there are:
Since a
contains an object reference, convert that object to a primitive, preferring a number to a string if possible:
- Arrays don't provide a way of converting to number, so we end up doing (effectively)
a.toString()
a.toString()
calls a.join()
, which joins the entries together as strings with a comma in between
- So we end up with
"2"
.
Now we have "2" < 10
Since one of those is a number, the operator coerces the other one to number, giving us 2 < 10
- The result of
2 < 10
is true
This strategy sometimes, even frequently, means the <=
operator ends up comparing NaN
to something. For instance, if a
were a non-array object:
var a = {};
console.log(a.toString()) // "[object Object]"
console.log(a < 10); // false
The steps would be:
Since a
contains an object reference, convert that object to a primitive, preferring a number to a string if possible:
Plain objects don't support conversion to number, so we end up doing (effectively) a.toString()
.
As you can see in the snippet above, that gives us "[object Object]"
Now we have "[object Object]" < 10
Since one of those is a number, the operator coerces the other one to number. "[object Object]"
coerced to a number is NaN
.
The result of NaN < 10
is false
, because all comparisons involving NaN
(including ===
) result in false
. (Yes, really; NaN === NaN
is false
.)
(Thanks Rajesh for suggesting the {} < 10
example and providing the initial version of the above.)