If compareFn
is not supplied, all non-undefined
array elements are sorted by converting them to strings and comparing strings in UTF-16 code units order. For example, "banana" comes before "cherry". In a numeric sort, 9 comes before 80, but because numbers are converted to strings, "80" comes before "9" in the Unicode order. All undefined
elements are sorted to the end of the array.
Note: In UTF-16, Unicode characters above \uFFFF
are encoded as two surrogate code units, of the range \uD800
-\uDFFF
. The value of each code unit is taken separately into account for the comparison. Thus the character formed by the surrogate pair \uD855\uDE51
will be sorted before the character \uFF3A
.
If compareFn
is supplied, all non-undefined
array elements are sorted according to the return value of the compare function (all undefined
elements are sorted to the end of the array, with no call to compareFn
).
So, the compare function has the following form:
function compareFn(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
return 0;
}
More formally, the comparator is expected to have the following properties, in order to ensure proper sort behavior:
-
Pure: The comparator does not mutate the objects being compared or any external state. (This is important because there's no guarantee when and how the comparator will be called, so any particular call should not produce visible effects to the outside.)
-
Stable: The comparator returns the same result with the same pair of input.
-
Reflexive:
compareFn(a, a) === 0
. -
Symmetric:
compareFn(a, b)
and compareFn(b, a)
must both be 0
or have opposite signs. -
Transitive: If
compareFn(a, b)
and compareFn(b, c)
are both positive, zero, or negative, then compareFn(a, c)
has the same positivity as the previous two.
A comparator conforming to the constraints above will always be able to return all of 1
, 0
, and -1
, or consistently return 0
. For example, if a comparator only returns 1
and 0
, or only returns 0
and -1
, it will not be able to sort reliably because symmetry is broken. A comparator that always returns 0
will cause the array to not be changed at all, but is reliable nonetheless.
The default lexicographic comparator satisfies all constraints above.
To compare numbers instead of strings, the compare function can subtract b
from a
. The following function will sort the array in ascending order (if it doesn't contain Infinity
and NaN
):
function compareNumbers(a, b) {
return a - b;
}
The sort
method can be conveniently used with function expressions or arrow functions.
const numbers = [4, 2, 5, 1, 3];
numbers.sort(function (a, b) {
return a - b;
});
console.log(numbers);
const numbers2 = [4, 2, 5, 1, 3];
numbers2.sort((a, b) => a - b);
console.log(numbers2);
Arrays of objects can be sorted by comparing the value of one of their properties.
const items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic', value: 13 },
{ name: 'Zeros', value: 37 }
];
items.sort((a, b) => a.value - b.value);
items.sort((a, b) => {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});