sort in JavaScript uses the Array.prototype.sort() method. By default, it converts array elements to strings and orders their UTF-16 values, so string arrays often sort as expected but number arrays can produce surprising results.
For numbers, pass a comparator: (a, b) => a – b sorts ascending, while (a, b) => b – a sorts descending. The same comparator pattern works for numeric properties on objects.
How does sort in JavaScript behave by default for strings and numbers?
Without a comparator, sort() compares string representations. For example, [‘pear’, ‘apple’, ‘orange’].sort() returns [‘apple’, ‘orange’, ‘pear’]. Uppercase and lowercase characters can appear in separate groups because their character codes differ.
The same rule causes numeric errors. [10, 2, 1, 21].sort() becomes [1, 10, 2, 21], because the values are compared as ’10’, ‘2’, ‘1’, and ’21’. Use a numeric comparator whenever the array contains numbers. Default sorting is appropriate only when its string-based ordering matches the intended result.
How does a JavaScript numeric sort handle ascending and descending values?
A comparator receives two elements, a and b. A negative return value places a before b; a positive value places b first; zero treats them as equal. This return-value contract lets JavaScript calculate numeric order directly.
For ascending order, subtract the second value from the first:
const ascending = numbers.sort((a, b) => a – b);
If a is smaller than b, the result is negative, so a moves earlier. If a is larger, the result is positive, so it moves later. This is the standard JavaScript numeric sort for low-to-high values.
To sort descending in JavaScript, reverse the subtraction:
const descending = numbers.sort((a, b) => b – a);
Now a larger value produces a negative result and moves toward the start of the array. Both calls mutate numbers; use a copy when the original order matters.
How do you sort objects by a property?
For objects, the comparator should read the property used for ordering. This example sorts players by a numeric score from lowest to highest:
players.sort((a, b) => a.score – b.score);
For highest to lowest, switch the operands:
players.sort((a, b) => b.score – a.score);
String properties need a string comparator. For example, players.sort((a, b) => a.name.localeCompare(b.name)) orders names alphabetically according to the available locale rules. For descending names, compare b.name with a.name. Keep the property types consistent so the comparator returns reliable results.
What changes when sort() mutates, and when should you use toSorted()?
sort() changes the existing array and returns that same array. Declaring the array with const does not prevent this mutation; it only prevents assigning a different array to the variable.
Copy the array before sorting when other code needs the original order:
const ascending = […numbers].sort((a, b) => a – b);
toSorted() provides the non-mutating alternative in modern JavaScript. It returns a new sorted array while leaving the source unchanged:
const descending = numbers.toSorted((a, b) => b – a);
Use sort() when changing the current array is intentional. Use toSorted(), or a spread copy followed by sort(), when immutability is required.
