SKU // 68

JavaScript Array Sort

Sorting puts elements in order: alphabetical names, highest scores first, earliest dates first. JavaScript's sort() is flexible, but its default behavior surprises nearly everyone the first time they sort numbers.

// Sorting Strings

const names = ["Cal", "ava", "Ben", "dee"];
names.sort();
console.log(names);
["Ben", "Cal", "ava", "dee"]

By default, sort compares character codes, and every uppercase letter comes before every lowercase one. For human-friendly alphabetical order, use localeCompare:

names.sort((a, b) => a.localeCompare(b));
console.log(names);
["ava", "Ben", "Cal", "dee"]

For Z-to-A order, sort and then reverse(), which flips the order of any array:

const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort().reverse();
console.log(fruits);
["Orange", "Mango", "Banana", "Apple"]

// The Number Trap

const nums = [10, 9, 1, 100, 25];
nums.sort();
console.log(nums);
[1, 10, 100, 25, 9]

The default sort turns every element into a string first, then sorts alphabetically. As text, "100" comes before "25" because "1" comes before "2", just like "apple" comes before "banana".

Rule
Never call sort() with no arguments on numbers. Always give it a compare function.

// Compare Functions

A compare function receives two elements, a and b, and returns a number that tells sort which goes first:

negativea goes before b
positiveb goes before a
0keep their current order

For numbers, subtraction produces exactly that:

const nums = [10, 9, 1, 100, 25];

nums.sort((a, b) => a - b);    // ascending:  [1, 9, 10, 25, 100]
nums.sort((a, b) => b - a);    // descending: [100, 25, 10, 9, 1]
[1, 9, 10, 25, 100] [100, 25, 10, 9, 1]
Memory Trick
a - b is ascending (small first). b - a is the reverse, so big first.

How it plays out: when sort compares 40 and 100, it calls the function with a = 40 and b = 100. The result, 40 - 100 = -60, is negative, so 40 goes first. sort repeats this for pairs until the whole array is in order.

Older code writes the same compare function with the function keyword. It works exactly like the arrow version:

nums.sort(function(a, b) { return a - b; });

// Sorting Objects by a Property

const players = [
  { name: "Kai",  score: 420 },
  { name: "Mo",   score: 980 },
  { name: "Lena", score: 655 }
];

players.sort((a, b) => b.score - a.score);          // high score first
console.log(players.map(p => p.name).join(", "));

players.sort((a, b) => a.name.localeCompare(b.name)); // alphabetical
console.log(players.map(p => p.name).join(", "));
Mo, Lena, Kai Kai, Lena, Mo

Dates sort the same way as numbers, since subtracting two dates gives milliseconds: events.sort((a, b) => a.date - b.date).

Comparing strings without localeCompare

You will also see string properties compared with < and >. Converting to lowercase first fixes the uppercase-first problem, and the function returns -1, 1, or 0 by hand:

const cars = [{ type: "Volvo" }, { type: "saab" }, { type: "BMW" }];

cars.sort((a, b) => {
  const x = a.type.toLowerCase();
  const y = b.type.toLowerCase();
  if (x < y) return -1;
  if (x > y) return 1;
  return 0;
});

console.log(cars.map(c => c.type).join(", "));
BMW, saab, Volvo

Ties keep their order (stable sort)

When two elements compare as equal, sort keeps them in the order they started in. This has been guaranteed since 2019, and it means you can sort by one thing, then another:

const items = [
  { n: "A", price: 2 }, { n: "B", price: 1 },
  { n: "C", price: 2 }, { n: "D", price: 1 }
];
items.sort((a, b) => a.price - b.price);
console.log(items.map(i => i.n).join(""));
BDAC

B stays ahead of D, and A ahead of C, because that is how they started.

// sort() Changes the Original

const original = [3, 1, 2];
const sorted = original.sort((a, b) => a - b);

console.log(original);   // [1, 2, 3]  (changed!)
console.log(sorted === original);   // true  same array

To keep the original, use toSorted() (added in 2023) or sort a copy:

const original = [3, 1, 2];

const s1 = original.toSorted((a, b) => a - b);   // new array
const s2 = [...original].sort((a, b) => a - b);  // same idea, works everywhere

console.log(original, s1);   // [3, 1, 2]  [1, 2, 3]
[3, 1, 2] [1, 2, 3]

// Reversing

[1, 2, 3].reverse()      // [3, 2, 1]  changes the original
[1, 2, 3].toReversed()   // [3, 2, 1]  returns a new array

// Highest and Lowest Without Sorting

If you only need the maximum or minimum, sorting the whole array is overkill:

const temps = [71, 64, 88, 79];
Math.max(...temps)   // 88
Math.min(...temps)   // 64

You could also sort first and take [0] and the last element, but sorting a whole array just to read two values is slow. Older code uses Math.max.apply(null, temps), which does the same job as the spread version; spread is easier to read.

Watch out: huge arrays
Spread turns every element into a separate argument, and there is a limit on how many arguments a function can take. In Chrome, Math.max(...bigArray) with 200,000 elements throws RangeError: Maximum call stack size exceeded. For very large arrays, use a plain loop.
function arrayMax(arr) {
  let max = -Infinity;
  for (const n of arr) {
    if (n > max) max = n;
  }
  return max;
}

console.log(arrayMax([71, 64, 88, 79]));
88

Starting at -Infinity guarantees that any real number is bigger, so the first element always replaces it. This loop is also the fastest way.

// Shuffling Correctly

You may see arr.sort(() => Math.random() - 0.5) suggested for shuffling. It looks random but is not fair: some orders come up far more often than others. Use the Fisher-Yates shuffle instead:

function shuffle(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    const temp = a[i];                             // swap a[i] and a[j]
    a[i] = a[j];
    a[j] = temp;
  }
  return a;
}

console.log(shuffle(["A", "B", "C", "D"]));   // a different order each run

// Quick Check

What does this log?

console.log(["b", "a", "C"].sort());
Show answer
["C", "a", "b"]. The default sort compares character codes, and every uppercase letter comes before every lowercase one.

A compare function returns a negative number for (a, b). What happens?

  1. b goes before a
  2. a goes before b
  3. Both are removed
  4. The sort stops
Show answer
B. Negative means a first, positive means b first, and 0 keeps their current order.

What does this log?

const a = [3, 1, 2];
const b = a.toSorted((x, y) => x - y);
console.log(a[0], b[0]);
Show answer
3 1. toSorted returns a sorted copy and leaves a alone. With sort, both would print 1.

// Try It

  1. Click Open Playground and run it. Then sort the numbers correctly, ascending and then descending
  2. Sort a list of names that mixes capital and lowercase letters, first with sort() then with localeCompare
  3. Sort an array of product objects by price, cheapest first, without changing the original
  4. Copy the shuffle() function into the Playground and shuffle a deck of 10 numbers several times
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:41 AM ET