JavaScript relational comparison operator type coercion is defined in the JavaScript specification, specifically in sections 11.8 to 11.8.5 which describe the operators, and sections 9.1 (ToPrimitive) and 9.3 (ToNumber) which describe the process of coercing the operands.
In short, the 4 comparison operators (<
, >
, <=
, and >=
) do their best to convert each operand to a number, then compare the numbers. The exception is when both operands are strings, in which case they are compared alphabetically.
Specifically,
If an argument o
is an object instead of a primitive, try to convert it to a primitive value by calling o.valueOf()
or - if o.valueOf
wasn't defined or didn't return a primitive type when called - by calling o.toString()
If both arguments are Strings, compare them according to their lexicographical ordering. For example, this means "a" < "b"
and "a" < "aa"
both return true.
Otherwise, convert each primitive to a number, which means:
undefined
-> NaN
Null
-> +0
Boolean
primitive type -> 1
if true
, +0
if false
String
-> try to parse a number from the string
Then compare each item as you'd expect for the operator, with the caveat that any comparison involving NaN
evaluates to false
.
So, this means the following:
console.log(true > null); //prints true
console.log(true > false); //prints true
console.log("1000.0" > 999); //prints true
console.log(" 1000\t\n" < 1001); //prints true
var oVal1 = { valueOf: function() { return 1; } };
var oVal0 = { toString: function() { return "0"; } };
console.log(oVal1 > null); //prints true
console.log(oVal0 < true); //prints true
console.log(oVal0 < oVal1); //prints true