sort()
method: From basics to custom sortingData is most valuable when it’s well-organized, easy to read, and easy to understand. As a developer, you might need to sort products by price or arrange names alphabetically to quickly extract relevant information.
There are two primary array sorting methods in JavaScript: the Array.prototype.sort
method and the Array.prototype.toSorted
method. Both of these techniques have built-in sorting behavior, and are equally customizable. In this article, we’ll cover everything from the different use cases for each method, default sorting behavior, and how you can customize the sorting methods to meet your needs.
Then, we’ll learn how you can use the two sorting methods with the localeCompare
string method and the Intl.Collator
object for language-sensitive string array sorting.
sort()
array method in JavaScriptThe sort()
method is the primary sorting method in JavaScript. It takes an optional compare function as an argument. The JavaScript sort()
method sorts the array accordingly before returning a reference to the original array. The key thing to note here is that the sort()
method simply mutates the original array rather than creating a new array, as you can see here:
js array.sort(compareFunction)
The compareFunction
determines our sorting behavior. If you don’t pass a compare function as an argument, this function will first convert the elements into strings and then use the numeric values of the UTF-16 code units to sort the elements in ascending order. Let’s look at the example below:
js const array = [20, 123, "🥚", "🐔"]; console.log(array.sort());
If you’re still new to JavaScript, the results of running the code above might surprise you. Let’s take a look at the result of the sorted array:
js const sortedArray = [ 123, 20, '🐔', '🥚' ];
See how 123
has been sorted before 20
, even though 123
is a bigger number? This is because we invoked the sort()
method without a callback. With no callback, elements are first coerced to strings before being sorted in ascending order of the UTF-16 code units of its constituent characters.
The first element in the unsorted array is 20
. When it is coerced to a string, the first character in the resulting string is "2"
and the second character is "0"
. The Unicode code point assigned to the character "2"
is U+0032(50 in decimal), and for "0"
is U+0030(48 in decimal).
Because they both lie in the basic multilingual plane (BMP), both code points are encoded as single 16-bit code units in UTF-16 character encoding:
js const array = [20, 123, "🥚", "🐔"]; const string = array[0].toString(); // 20 console.log(string.length); // 2 console.log(string.charCodeAt(0)); // 50 console.log(string.charCodeAt(1)); // 48
Similarly, the second element in our unsorted array is 123
. When we coerce the integer 123
to a string, the first character in the resulting string will be "1"
, the second character will be "2"
, and the third character will be "3"
.
The Unicode code point assigned to the character "1"
is U+0031(49 in decimal), for the character "2"
is U+0032(50 in decimal), and for "3"
is U+0033(51 in decimal).
All three code points lie in the BMP like before. Therefore, each one of them is encoded as a single 16-bit code unit in the UTF-16 character encoding:
js const array = [20, 123, "🥚", "🐔"]; const string = array[1].toString(); console.log(string.length); // 3 console.log(string.charCodeAt(0)); // 49 console.log(string.charCodeAt(1)); // 50 console.log(string.charCodeAt(2)); // 51
Similar to integers, all other non-undefined JavaScript primitives are first coerced to strings when you invoke the sort()
method without a callback. All undefined
values and empty slots are sorted to the end of the array.
The last two entries in our unsorted example array are both emojis. Since they are already strings, they are not coerced to strings like the other JavaScript primitives.
The Unicode code point assigned to the egg emoji, "🥚"
, is U+1F95A(129370 in decimal) and that for the chicken emoji, "🐔"
, is U+1F414(128020 in decimal). Both code points lie in the supplementary plane outside the BMP.
In UTF-16 character encoding, Unicode code points in the supplementary plane cannot be encoded using single 16-bit code units. As a result, they’re encoded using double 16-bit code units referred to as surrogate pairs. This explains why the length of the strings for both "🥚"
and "🐔"
are 2:
js console.log("🥚".length === 2) // true console.log("🐔".length === 2) // true
The first UTF-16 code unit in a surrogate pair is referred to as the leading or higher surrogate, and the second is referred to as the trailing or lower surrogate.
The code point assigned to the egg emoji is U+1F95A(129370 in decimal). In UTF-16 character encoding, this will be encoded into its respective leading and trailing surrogate pairs U+D83E(55358 in decimal) and U+DD5A(56666 in decimal):
js const array = [20, 123, "🥚", "🐔"]; const eggEmoji = array[2]; console.log(eggEmoji.charCodeAt(0)); // 55358 console.log(eggEmoji.charCodeAt(1)); // 56666
Similarly, the Unicode code point assigned to the chicken emoji is U+1F414(128020 in decimal). In UTF-16 character encoding, this will be encoded into its respective leading and trailing surrogate pairs U+D83D (55357 in decimal) and U+DC14(56340 in decimal):
js const array = [20, 123, "🥚", "🐔"]; const chickenEmoji = array[3]; console.log(chickenEmoji.charCodeAt(0)); // 55357 console.log(chickenEmoji.charCodeAt(1)); // 56340
After coercing non-string values to strings as described above, the UTF-16 code units of the characters in the respective strings are used for sorting the elements of the array in ascending order.
In our example array above, the first element of the array is 20
. The UTF-16 code unit of its first character "2"
is 50 when coerced to a string.
The second element of our array is 123
. The UTF-16 code unit of its first character "1"
when coerced to a string is 49.
The third and fourth characters are the egg and chicken emojis, respectively. The leading surrogate for the egg emoji is 55358 in decimal, and 55357 for the chicken emoji.
Finally, JavaScript will use these code units to sort the elements of the array in ascending order. Therefore, JavaScript doesn’t use the actual characters but rather the numerical values of their UTF-16 code units. The lowest code unit in our example above is 49, followed by 50, 55357, and 55358.
That explains why 123
comes before 20
in our sorted array, despite 123
being greater. Then the chicken and egg emojis come into the third and fourth positions, respectively.
If your array is sparse or has undefined
elements, the empty slots and undefined
elements are sorted to the end of the array. The empty slots are sorted after all the undefined
elements.
Let’s now sort our example array after turning it into a sparse array by adding an empty slot and an undefined
value, as seen in the example below:
js const array = [20, undefined, , 123, "🥚", "🐔"]; console.log(array.sort()); // [ 123, 20, '🐔', '🥚', undefined, <1 empty item> ]
The empty slot and the undefined
element are now sorted to the end of the array when you execute the code above.
We just explored JavaScript’s sort()
method when invoked without a callback. However, this isn’t the only way you have to sort; you can customize this behavior by passing a callback function.
The callback function will determine whether to sort the array in ascending or descending order. In the next section, we’ll get into how to use the callback function.
To recap the previous section, the JavaScript sort()
array method takes an optional compare function as a callback. If you don’t pass a callback, the array’s elements will be coerced to strings and are sorted in ascending order of the numerical values of their UTF-16 code units.
However, the default JavaScript sorting behavior is rarely what you need. More often than not, you’d want to custom-sort elements in ascending or descending order.
If you want custom sorting behavior, you must pass a compare function as a callback. The compare function takes two values as arguments. It will only be invoked with non-undefined values. All undefined
values and empty slots will be sorted to the end of the array.
The compare function should return a negative number if the first argument is to be sorted before the second argument. It should return a positive number if the second argument is to be sorted before the first, and a zero if they are equal and their original order is to be maintained.
The example code below gives us an idea of what the compare function should look like:
js const compareFunction = (arg1, arg2) => { if ("arg1 is to be sorted before arg2") { return "a negative number"; } else if ("arg1 is to be sorted after arg2") { return "a positive number"; } return "zero to maintain the original order of arg1 and arg2"; }
To sort an array of numbers in ascending order, your compare function should look something like the code below:
js const array = [23, -45, 78]; array.sort((a, b) => { if(a < b) return -1; if(a > b) return 1; return 0; })
The returned values from the compare function don’t necessarily have to be -1
and 1
. You can return any negative or positive value. You can make the above sorting function more succinct, like so:
js const array = [23, -45, 78]; array.sort((a, b) => a - b);
We can apply a similar logic to sort an array of numbers in descending order by switching the comparison operator that we see in the if
conditions above. Your compare function should then look like this:
js const array = [23, -45, 78]; array.sort((a, b) => { if(a > b) return -1; if(a < b) return 1; return 0; })
You can also write the above compare function like this:
js const array = [23, -45, 78]; array.sort((a, b) => b - a);
The sort()
method doesn’t just sort number arrays. You can use it to sort an array of primitive values, objects, or a mix of both primitive values and objects.
As an example, let’s take an array of objects sorted in alphabetical order by name
property:
js const students = [ { name: "Aggy Doe", age: 19 }, { name: "Jane Doe", age: 16 }, { name: "Kent Doe", age: 14 }, { name: "Mark Doe", age: 19 }, ];
We can use the sort()
method to sort the above objects in ascending order of the age
property, like so:
js students.sort((a, b) => a.age - b.age);
Our sorted students
array is all set. You’ll notice that two students are the same age. If you’re using ECMAScript version 10(2019) and above, JavaScript guarantees sort stability. Earlier versions of ECMAScript do not guarantee sort stability.
In a stable sort, the original order is maintained if there is a tie. We can see that in our students
array, where the original order is maintained even for our students of the same age:
js const students = [ { name: "Kent Doe", age: 14 }, { name: "Jane Doe", age: 16 }, { name: "Aggy Doe", age: 19 }, { name: "Mark Doe", age: 19 }, ];
As explained above, sort
does not create a new array; it mutates the original array. If you don’t want to mutate the original array, first create a new array before sorting or use the toSorted
array method instead. In the next section, we’ll take a look at the toSorted
method.
In the example below, we’re using structuredClone
to create a copy of the original array before sorting. You can also use other built-in features like spread syntax to clone the original array:
js const clone = structuredClone(students); clone.sort((a, b) => a.age - b.age);
sort()
method’s compare functionThe compare callback function in the sort()
and toSorted
methods must conform to the properties below to carry out custom sorting behaviors. If your compare function doesn’t conform to these properties, then it is not well defined, meaning its behavior will vary unpredictably across JavaScript engines.
The callback you pass to the sort()
function should be a pure function. If you invoke it with the same pair of arguments, it should always return the same output.
The function’s output should be determined exclusively by its input, without relying on external state or variables. The function must also avoid side effects, such as modifying external state or performing I/O operations.
The compare function must be pure because there is no guarantee of how or when it’ll be invoked.
Your compare function should be reflexive. If both arguments are the same, the compare function should return 0
so that the original order of the entries is maintained in the sorted array. Check out an example below:
js console.log(compareFunction(a, a) === 0); // true
The compare function should be anti-symmetric. This means the return values of invoking compareFunction(a, b)
and compareFunction(b, a)
should be of opposite signs or zero.
Finally, the compare function callback should be transitive. If compareFunction(a, b)
and compareFunction(b, c)
are both positive, negative, or zero, then compareFunction(a, c)
has the same positivity as the other two.
toSorted
array method in JavaScriptWe’ve done a deep dive of the sort()
method. However, one of the sort()
method’s limitations is that it mutates the original array, forcing you to make a copy of the original array beforehand if you want to keep the array as is.
As a workaround for that hassle, you can also use the handy built-in toSorted
array method. Unlike sort
, the toSorted
JavaScript array method doesn’t mutate the original array. Instead, it returns a new array.
The toSorted
method is similar to sort
. If you don’t invoke it with a compare callback, the elements are coerced to strings, and the UTF-16 code units of the resulting strings are used to sort the elements in ascending order:
js const array = [20, 123, "🥚", "🐔"]; const sortedArray = array.toSorted(); console.log(array === sortedArray); // false console.log(sortedArray); // [ 123, 20, '🐔', '🥚' ]
To implement custom sorting in the toSorted
method, pass a compare function, just as with the sort()
method. This function takes two arguments and should return a negative value if the first argument comes before the second, a positive value if it comes after, and zero if their order remains unchanged.
In the example below, we’re sorting the array of numbers in ascending order:
js const array = [20, 123, -67]; const sortedArray = array.toSorted((a, b) => a - b); console.log(array === sortedArray); // false console.log(sortedArray); // [ -67, 20, 123 ]
Like with sorted
, the toSorted
method sorts undefined
elements and empty slots to the end of the array. The compare function is not invoked for the undefined
elements and the empty slots.
Be aware that toSorted
is a fairly new method. Therefore, it might not be widely supported across web browsers and JavaScript runtime environments.
JavaScript has built-in locale-aware functions that you can use to sort string arrays. These functions are the Intl.Collator
object and the String.prototype.localeCompare
method.
The primary function of the Intl.Collator
object is for language-sensitive string comparison. Different languages have their own rules for string comparison. You can use Intl.Collator
for locale-sensitive sorting of string arrays like in the example below:
js const swedishCollator = new Intl.Collator("sv"); const germanCollator = new Intl.Collator("de"); const data = ["Z", "a", "z", "ä"]; console.log(data.toSorted(swedishCollator.compare)); // [ 'a', 'z', 'Z', 'ä' ] console.log(data.toSorted(germanCollator.compare)); // [ 'a', 'ä', 'z', 'Z' ]
The Intl.Collator.prototype.compare
method takes a pair of strings you want to compare as arguments and returns a negative number if the first argument comes before the second, a positive number if the first argument comes after the second, and a zero if they’re equal. That’s why you can pass it as an argument to either the [Array.prototype.sort](https://blog.logrocket.com/guide-four-new-array-prototype-methods-javascript/)``()
method or Array.prototype.toSorted
method.
You can also customize sort behavior by passing an optional second argument to Intl.Collator
. Check the documentation to learn more.
Similarly, you can also use the String.prototype.localeCompare
method to sort string arrays. It returns a number indicating whether this
string comes before, after, or is the same as the provided string:
js const referenceString = "Jane Doe"; console.log(referenceString.localeCompare("Chris Doe"));
If it returns a negative number, this
string comes before the comparison string. If it returns a positive number, this
comes after the comparison string, and a zero means this
is equivalent to the comparison string.
Therefore, you can also use the localeCompare
method with sort
or toSorted
methods to sort an array of strings in alphabetical order:
js const names = [ "Jane Doe", "Kim Doe", "Chris Doe", "Mia Doe", ] names.sort((a, b) => a.localeCompare(b)) console.log(names)
For browsers or runtime environments that implement the Intl.Collator
API, the localeCompare
method internally uses Intl.Collator
.
sort
and toSorted
methodsIn the previous sections, we used sort
and toSorted
as array instance methods. However, as with most array methods, both are generic functions. Their use is not limited to arrays.
You can use them to sort array-like objects. They only require the array-like object to have a length property and integer-keyed properties like arrays as in the example below:
js const object = { 0: 90, 1: 34, 2: -45, 3: 12, length: 4, }; Array.prototype.sort.call(object, (a, b) => a - b); console.log(object); // { '0': -45, '1': 12, '2': 34, '3': 90, length: 4 }
The example above sorts the given object in ascending order. You can also sort it in descending order by modifying the compare callback. The sort()
method mutates the original object and returns a reference to it.
If you don’t want to mutate the original object, you can use the toSorted
method similarly. Unlike sort
, the toSorted
method returns a new array, not an object:
js const object = { 0: 90, 1: 34, 2: -45, 3: 12, length: 4, }; const sortedObject = Array.prototype.toSorted.call(object, (a, b) => a - b); console.log(sortedObject); // [ -45, 12, 34, 90 ] console.log(sortedObject === object); // false
The sort
and toSorted
methods are built-in tools for sorting JavaScript arrays. By default, they convert elements to strings and sort them by UTF-16 code units, but you can customize their behavior using a compare function. The key difference is that sort
mutates the original array, while toSorted
returns a new one.
We’ve explored the more detailed alternatives for custom sorting behavior, which you can activate by comparing callback functions to modify the default sorting behavior. You can use the callback function to sort arrays of JavaScript primitives and objects using a certain criterion.
Both methods are generic and work on array-like objects with a length property and integer-keyed properties. Choosing between them depends on whether you want to modify the original array or keep it unchanged. Use the sort()
method if you want to mutate the original array and toSorted
if you don’t want to mutate the original array.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowVibe coding is taking the dev world by storm. Break down what it actually means, how the term became popularized, and why it’s catching on.
Discover the new full-stack React Framework, TanStack Start, and use it to build a simple developer portfolio styled with Tailwind CSS.
AI coding tools are growing in prominence. Explore the leading AI coding tools for 2025, from IDEs to conversational AI assistants.
Custom fonts provide your apps with a unique identity. Explore modern ways to add custom fonts in a React Native app, including Google Fonts.