Your sorting algorithm produces, in some instances, NaN, since undefined - someNum and someNum - undefined both result in NaN. This means that your callback is not consistent, which means that the resulting sort order is implementation-defined.
A function comparefn is a consistent comparison function for a set of values S if all of the requirements below are met for all values a, b, and c (possibly the same value) in the set S: The notation a <CF b means comparefn(a, b) < 0; a =CF b means comparefn(a, b) = 0 (of either sign); and a >CF b means comparefn(a, b) > 0.
- Calling comparefn(a, b) always returns the same value v when given a specific pair of values a and b as its two arguments. Furthermore, Type(v) is Number, and v is not NaN. Note that this implies that exactly one of a <CF b, a =CF b, and a >CF b will be true for a given pair of a and b.
If you ever return NaN from a .sort callback, your results can be anything at all: the behavior in such a case is undefined by the specification (though certain implementations might produce a result that makes more intuitive sense... or not). So, make sure never to return NaN. In this case, explicitly test to see if the .i property being iterated over is undefined, and substitute a different value for it - maybe Infinity or -Infinity.
const sanitize = val => val === undefined ? Infinity : val;
const notSorted = [
{i:0},
{i:5},
{i:2},
{i: undefined},
{i:3},
{i:1},
{i:4},
]
.sort((a, b) => sanitize(a.i) - sanitize(b.i))
.map(a => a.i);
console.log(notSorted);