JavaScript provides built-in methods to sort arrays, making it convenient for developers to manipulate data. There are two primary ways to sort an
array:
-
Array.prototype.sort()
: This method sorts the elements of an array in place and returns the sorted array.
-
Array.prototype.toSorted()
: This method is designed to return a new sorted array, leaving the original array unchanged.
The default sort order is lexicographic (dictionary) order, based on the string representation of the elements. This means that when sorting an
array of strings, numbers, or other elements, they are converted to strings and sorted according to their Unicode code points (UTF-16). For most
cases, this default behavior is suitable when sorting an array of strings.
However, it’s essential to be aware of potential pitfalls when sorting arrays of non-string elements, particularly numbers. The lexicographic order
may not always produce the expected results for numbers:
const numbers = [10, 2, 30, 1, 5];
numbers.sort(); // Noncompliant: lexicographic sort
console.log(numbers); // Output: [1, 10, 2, 30, 5]
To sort numbers correctly, you must provide a custom comparison function that returns the correct ordering:
const numbers = [10, 2, 30, 1, 5];
numbers.sort((a, b) => a - b);
console.log(numbers); // Output: [1, 2, 5, 10, 30]
Even to sort strings, the default sort order may give unexpected results. Not only does it not support localization, it also doesn’t fully support
Unicode, as it only considers UTF-16 code units. For example, in the code below, "eΔ"
is surprisingly before and after "éΔ"
.
To guarantee that the sorting is reliable and remains as such in the long run, it is necessary to provide a compare function that is both locale and
Unicode aware - typically String.localeCompare
.
const code1 = '\u00e9\u0394'; // "éΔ"
const code2 = '\u0065\u0301\u0394'; // "éΔ" using Unicode combining marks
const code3 = '\u0065\u0394'; // "eΔ"
console.log([code1, code2, code3].sort()); // Noncompliant: ["éΔ", "eΔ", "éΔ"], "eΔ" position is inconsistent
console.log([code1, code2, code3].sort((a, b) => a.localeCompare(b))); // ["eΔ", "éΔ", "éΔ"]