Array.sort() in JavaScript: sorting an array and avoiding the default order

sort orders an array in place and compares values as text by default. The comparison function is what makes the sort correct.
3 min read
Believemy logo

An array of numbers sorted by sort with no precaution comes back as [1, 10, 100, 9]. That is not a bug, it is the documented behavior, and it is probably the most widely met trap in the language.

Two things are worth knowing before writing a sort: sort changes the original array, and it compares text until it is told how to compare.


Definition

sort reorders the items of an Array in place and hands back that same array, not a copy. With no argument, each item is converted to a string, and the strings are then compared character by character.

JAVASCRIPT
const scores = [10, 9, 1, 100];

console.log(scores.sort());  // [ 1, 10, 100, 9 ]
console.log(scores);         // the original array was changed

console.log([10, 9, 1, 100].sort((a, b) => a - b));  // [ 1, 9, 10, 100 ]

"10" comes before "9" for the same reason "ab" comes before "b" in a dictionary: the first character decides. The comparison function restores the expected order.


The comparison function

It receives two items and returns a number. Only its sign matters, the exact value is irrelevant.

  • Negative the first item goes before the second.
  • Zero both keep their relative order.
  • Positive the second item goes before the first.
JAVASCRIPT
const products = [
  { name: "Keyboard", price: 89 },
  { name: "Mouse", price: 29 },
  { name: "Monitor", price: 249 },
];

products.sort((a, b) => a.price - b.price);
console.log(products.map((p) => p.name));  // [ 'Mouse', 'Keyboard', 'Monitor' ]

products.sort((a, b) => b.price - a.price);  // most expensive first

Swapping a and b flips the sort, which saves a call to reverse afterwards.


Sorting text, and sorting without changing anything

On accented words, the default comparison puts "Zoé" before "école", because it compares character codes rather than letters. localeCompare knows the rules of the language.

JAVASCRIPT
const words = ["éclair", "avion", "zèbre", "École"];

console.log(words.sort((a, b) => a.localeCompare(b, "fr")));
// [ 'avion', 'éclair', 'École', 'zèbre' ]

const original = [3, 1, 2];
const sorted = [...original].sort((a, b) => a - b);
console.log(original);  // [ 3, 1, 2 ], untouched
Good to know

Copying with Spread (...) before sorting is the habit to build as soon as the data is displayed somewhere else. The newer toSorted method does the same in a single step and leaves the original alone.


Frequently asked questions

Question

Why does [10, 9, 1] turn into [1, 10, 9]?

Because with no comparison function, the numbers are converted to text before being compared. "10" starts with the character "1", which comes before "9". Passing (a, b) => a - b settles the question for good on numbers.


Question

Is the sort stable?

Yes. Two items the comparison judges equal keep their original order, and the standard has guaranteed that since 2019. It allows sorting in two passes: by name first, by price second, and equal prices will still be ordered by name.


Question

How do you sort on several criteria at once?

By chaining comparisons with the || operator, which moves to the next criterion whenever the previous one returns zero: (a, b) => a.price - b.price || a.name.localeCompare(b.name, "en"). Sorting lists, dashboards and catalogs is covered in detail in the JavaScript course.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.