x >= x pattern in JavaScript
When reading source of D3.js I saw x >= x
pattern. If it is for detecting NaNs among numbers, why not just isNaN(x)
or x == x
?
Source, where I encountered it:
d3.min = function(array, f) {
var i = -1, n = array.length, a, b;
if (arguments.length === 1) {
while (++i < n) if ((b = array[i]) != null && b >= b) {
a = b;
break;
}
while (++i < n) if ((b = array[i]) != null && a > b) a = b;
} else {
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
a = b;
break;
}
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
}
return a;
};
Solution 1:
From my investigations, d3.min
is supposed to work on any kind of orderable values, not only numbers. isNaN
would only work numbers.
d3 was actually using ==
at some point. This commit introduced the x == x
test:
Unlike
Math.min
andMath.max
, it doesn't make sense to return negative or positive infinity ford3.min
andd3.max
; the D3 functions return the minimum value according to an arbitrary ordering, not by numeric value. Instead, the minimum or maximum of an empty array, or an array that contains only degenerate values, should always be undefined.
This commit changed x == x
to x <= x
(which was later again changed to x >= x
):
In addition to
NaN
, which is not equal to itself, you can have objects that are not orderable due to defined valueOf functions which return NaN. For example:var o = new Number(NaN);
Here,
o == o
is true, buto <= o
is false. Therefore it was possible for d3.min, d3.max and d3.extent to observe these non-orderable values rather than ignore them as intended. The fix is to check!(o <= o)
rather thano == o
.
Solution 2:
OK, I see that x >= x
gives false
for both NaN
and undefined
. (Unlike isNaN(x)
or x == x
.)
EDIT: While it is one of the use cases of x >= x
, in this case (thx @Felix Kling for pointing this out) undefined
is already being checked.