How does javascript do a relational comparison?
This post explains how javascript does when it compares two values with a relational operator ( <
, >
, <=
, >=
). If you are looking for equality comparison ( ==
, ===
), check this post instead.
Abstract Relational Comparison algorithm
The relation comparison in Javascript mainly follows the Abstract Relational Comparison algorithm, described in the ECMA specs. The less than ( <
) operator works as follows:
- Step 1: if any of the operands is not primitive, convert them to primitives, using
operand[Symbol.toPrimitive]('number')
. - Step 2: If both are string types, compare them lexicographically. Finish the algorithm.
- Step 3: If one of the operands is a string, and the other one is a BigInt. Convert the string value to BigInt with
BigInt(value)
. - Step 4: apply several following conversions (apply the ToNumber Conversions table unless the value is a BigInt).
Operand value | Converted value |
---|---|
undefined |
NaN |
null |
+0 |
true |
1 |
false |
0 |
number value | unchanged |
BigInt value | unchanged (toNumeric) |
string value | parseFloat(value) |
Symbol value | throw a TypeError |
- Step 5: If either value is
NaN
, returnfalse
. Otherwise, compare two values in numeric order.
Example 1
This is a demonstration example of date objects' comparisons.
new Date(2020, 0, 1) < new Date(2020, 8, 13) // returns true
- Step 1: Two operands are not primitive, they are converted to primitives using Date.prototype[@@toPrimitive] with
hint
benumber
.
new Date(2020, 0, 1)[Symbol.toPrimitive]('number') // returns 1577804400000
new Date(2020, 8, 13)[Symbol.toPrimitive]('number') // returns 1599922800000
- Step 5:
1577804400000
less than1599922800000
by their numerical order. The operator givestrue
as the result.
Longer explanation
- From Runtime Semantics: Evaluation, perform the Abstract Relational Comparison in step 5.
- in the Abstract Relational Comparison, follows Number::lessThan in step 4f.
- Return
undefined
at step 1, in Number::lessThan
- Back to Runtime Semantics: Evaluation, at the last step (step 7), because r is
undefined
, returnfalse
.
Example 2
new Date(2020, 0, 1) < 'a' // return false
'a' < new Date(2020, 0, 1) // return false
- Step 1: similar to example 1.
- Step 4:
'a'
is converted withparseFloat('a')
and becomesNaN
. - Step 5: return
false
in either case.
Example 3
new Date(2020, 0, 1) < 'Infinity' // return true
'Infinity' < new Date(2020, 0, 1) // return false
- Similar to example 2, except that
parseFloat('Infinity')
is evaluated to beInfinity
.