Array.prototype.toSorted()

Returns a sorted copy of an array, leaving the original in its existing order.

Signature
toSorted()
toSorted(compareFn)
  • Added in JavaScript ECMAScript 2023

Parameters

ParameterTypeDescription
$compareFnoptional(a: any, b: any) => number= undefinedDetermines order. Return a negative number to put a first, a positive number to put b first, 0 to keep them adjacent. Omitted, elements are compared as strings by UTF-16 code unit.

Return value

ArrayA new array with the elements sorted in ascending order; the original array is unchanged.

Errors

Throws a TypeError if compareFn is provided but is not a function, or if called on null or undefined.

Changelog

  • PHP ECMAScript 2019The underlying sort is required to be stable, so equal elements keep their original relative order in engines that follow the current spec.

toSorted() does what [...arr].sort() does, in one call: it copies the array and sorts the copy. The receiver keeps its original order, which removes the classic bug where sorting a list for display silently reorders the data everyone else is reading.

When to reach for it

Any time the array is not yours to reorder — component props, module-level constants, values in a store, or an array you are iterating elsewhere. It also composes: rows.toSorted(byDate).at(-1) reads the newest row without naming an intermediate.

What trips people up

  • The default comparison is lexicographic. Without a compareFn, elements are converted to strings, so [10, 1, 2].toSorted() is [1, 10, 2]. Pass (a, b) => a - b for numbers.
  • undefined values are always sorted to the end and never passed to compareFn; empty slots are treated the same way.
  • The copy is shallow, so sorting objects reorders references — mutating one still affects the source array's element.
  • Your comparator must be consistent. Returning a > b (a boolean) or a random number gives implementation-defined results.

Use Intl.Collator for human-readable text ordering; the default string comparison sorts by code unit, so "Z" comes before "a".

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Display a sorted view of a list without reordering the source data.
  • Sort component props or store state that must stay immutable.
  • Rank records by score and read the top one in a single chained expression.
  • Compare a sorted copy against the original to detect whether a list is already ordered.

Frequently asked questions

How do I sort an array without changing the original?

Call arr.toSorted(compareFn) — it copies first, then sorts the copy. It is equivalent to [...arr].sort(compareFn) but does not need the spread and works on frozen arrays.

Why does toSorted() put 10 before 9?

Because without a comparator elements are compared as strings, and "10" is less than "9". Pass (a, b) => a - b to sort numerically.

Is toSorted() stable?

Yes, the specification requires a stable sort, so elements your comparator reports as equal keep their original relative order. That lets you sort by a secondary key first and a primary key second.

More examples

Sorting objects by a field

Bo and Cy tie on age and keep their original relative order because the sort is stable. The copy holds the very same objects, as the identity check on the last line shows.

Example · javascript
const people = [
  { name: "Bo", age: 30 },
  { name: "Al", age: 25 },
  { name: "Cy", age: 30 },
];

const byAge = people.toSorted((a, b) => a.age - b.age);
console.log(byAge.map((p) => p.name));
console.log(people.map((p) => p.name));
console.log(byAge[1] === people[0]);

toSorted() vs sort()

sort() returns the same array it reordered, so mutated === source is true and the original is gone. toSorted() returns a new array and therefore also works on a frozen one, which sort() cannot.

Example · javascript
const source = [3, 1, 2];

const copy = source.toSorted((a, b) => a - b);
console.log(copy, source);

const mutated = source.sort((a, b) => a - b);
console.log(mutated === source, source);

console.log(Object.freeze([3, 1, 2]).toSorted((a, b) => a - b));

Human-readable text order

The default sort compares UTF-16 code units, so uppercase and accented letters land in the wrong places. Intl.Collator.compare produces the ordering a reader expects.

Example · javascript
const words = ["apple", "Banana", "cherry", "Ärger"];

console.log(words.toSorted());

const collator = new Intl.Collator("en", { sensitivity: "base" });
console.log(words.toSorted(collator.compare));

Discussion

  • Be the first to comment on this lesson.