Sorting arrays of objects in JavaScript
Sorting arrays is a daily basis task for many developers. In this article, we will see how to sort an array of objects in JavaScript without any third-party library. This article is a quick reminder for developers.
Let's use the fake user list below (freely generated with mockaroo).
type UserBasic = {
id: number;
firstName: string;
lastName: string;
email: string;
createdAt: string;
};
const userList: UserBasic[] = [
{
id: 1,
firstName: 'Aurélie',
lastName: 'Chelley',
email: '[email protected]',
createdAt: '2025-02-24T22:52:59Z',
},
{
id: 2,
firstName: 'Maëly',
lastName: 'Fishly',
email: '[email protected]',
createdAt: '2025-05-11T17:39:37Z',
},
{
id: 3,
firstName: 'Cloé',
lastName: 'Andrioli',
email: '[email protected]',
createdAt: '2023-10-16T08:56:47Z',
},
{
id: 4,
firstName: 'Loïs',
lastName: 'Gilloran',
email: '[email protected]',
createdAt: '2020-05-17T13:15:38Z',
},
{
id: 5,
firstName: 'Grégory',
lastName: 'McGuiness',
email: '[email protected]',
createdAt: '2020-06-13T13:36:32Z',
},
{
id: 6,
firstName: 'Ruò',
lastName: 'Marl',
email: '[email protected]',
createdAt: '2022-05-26T22:11:32Z',
},
{
id: 7,
firstName: 'Zhì',
lastName: 'Cartwight',
email: '[email protected]',
createdAt: '2025-06-22T06:27:32Z',
},
{
id: 8,
firstName: 'Grégoire',
lastName: 'McGuiness',
email: '[email protected]',
createdAt: '2024-11-11T18:29:20Z',
},
{
id: 9,
firstName: 'Amélie',
lastName: 'Chander',
email: '[email protected]',
createdAt: '2026-04-24T04:41:59Z',
},
{
id: 10,
firstName: 'Loïc',
lastName: 'McNicol',
email: '[email protected]',
createdAt: '2026-03-10T16:39:19Z',
},
];
From "Sort" to "toSorted"
The most common way to sort an array is to use the sort method but there is a newer way with the toSorted method (Baseline widely available in all browsers).
The toSorted method preserves the original array by returning a new array (which is often a good practice) while sort() mutates the original array.
Sorting an array of objects is simply done by comparing one or more properties of the objects. For this, the optional toSorted or sort method first parameter ( compareFn ) is crucial.
If omitted, the array elements are converted to strings, then sorted according to each character's Unicode code point value.
Example: ascending sort by last name
You have to use localeCompare to get the right sort order for non-ASCII characters like accented characters.
// Sort the users by last name ( asc )
const usersByName = userList.toSorted((a, b) => {
return a.lastName.localeCompare(b.lastName);
});
console.log(usersByName.map(({ firstName, lastName }) => lastName + ' ' + firstName));
/*
[
"Andrioli Cloé",
"Cartwight Zhì",
"Chander Amélie",
"Chelley Aurélie",
"Fishly Maëly",
"Gilloran Loïs",
"Marl Ruò",
"McGuiness Grégory",
"McGuiness Grégoire",
"McNicol Loïc"
]
*/
Easy like pie. But in real world, users are often sorted by two or more properties. In this example the McGuiness brothers are not sorted the right way ( Grégory should be after Grégoire ).
Example: ascending sort by last name and then first name
Sorting by multiple properties can be done using the || operator.
// Sort the users by last name and then first name ( asc )
const usersByFullName = userList.toSorted((a, b) => {
return a.lastName.localeCompare(b.lastName) || a.firstName.localeCompare(b.firstName);
});
console.log(usersByFullName.map(({ firstName, lastName }) => lastName + ' ' + firstName));
/*
[
"Andrioli Cloé",
"Cartwight Zhì",
"Chander Amélie",
"Chelley Aurélie",
"Fishly Maëly",
"Gilloran Loïs",
"Marl Ruò",
"McGuiness Grégoire",
"McGuiness Grégory",
"McNicol Loïc"
]
*/
Now the McGuiness brothers are sorted the right way.
Example: descending sort by last name and then first name
To sort in descending order, swap the arguments: b.localeCompare(a) instead of a.localeCompare(b).
// Sort the users by last name and then first name ( desc )
const usersByFullNameDesc = userList.toSorted((a, b) => {
return b.lastName.localeCompare(a.lastName) || b.firstName.localeCompare(a.firstName);
});
console.log(usersByFullNameDesc.map(({ firstName, lastName }) => lastName + ' ' + firstName));
/*
[
"McNicol Loïc",
"McGuiness Grégory",
"McGuiness Grégoire",
"Marl Ruò",
"Gilloran Loïs",
"Fishly Maëly",
"Chelley Aurélie",
"Chander Amélie",
"Cartwight Zhì",
"Andrioli Cloé"
]
*/
Great, we have our users sorted by last name and first name in descending order.
Example: sort by creation date
Sorting dates can be a little trickier. It depends on the date format.
ISO 8601
If the date is in ISO 8601 format ( YYYY-MM-DDTHH:mm:ssZ ), you can simply use the localeCompare method, like for any other string.
// Sort the users by creation date ( asc )
const usersByCreatedAt = userList.toSorted((a, b) => {
// For ISO 8601 dates
return a.createdAt.localeCompare(b.createdAt);
});
console.log(usersByCreatedAt.map(({ firstName, lastName }) => lastName + ' ' + firstName + ' ' + createdAt));
/*
[
"Gilloran Loïs 2020-05-17T13:15:38Z",
"McGuiness Grégory 2020-06-13T13:36:32Z",
"Marl Ruò 2022-05-26T22:11:32Z",
"Andrioli Cloé 2023-10-16T08:56:47Z",
"McGuiness Grégoire 2024-11-11T18:29:20Z",
"Chelley Aurélie 2025-02-24T22:52:59Z",
"Fishly Maëly 2025-05-11T17:39:37Z",
"Cartwight Zhì 2025-06-22T06:27:32Z",
"McNicol Loïc 2026-03-10T16:39:19Z",
"Chander Amélie 2026-04-24T04:41:59Z"
]
*/
Other date formats
If the date uses another format, you should parse it into timestamps using the Date.parse method.
The
Date.parse()static method parses a string representation of a date, and returns the date's timestamp
const usersByCreatedAt = userList.toSorted((a, b) => {
return Date.parse(a.createdAt) - Date.parse(b.createdAt);
});
console.log(usersByCreatedAt.map(({ firstName, lastName }) => lastName + ' ' + firstName + ' ' + createdAt));
/*
[
"Gilloran Loïs 2020-05-17T13:15:38Z",
"McGuiness Grégory 2020-06-13T13:36:32Z",
"Marl Ruò 2022-05-26T22:11:32Z",
"Andrioli Cloé 2023-10-16T08:56:47Z",
"McGuiness Grégoire 2024-11-11T18:29:20Z",
"Chelley Aurélie 2025-02-24T22:52:59Z",
"Fishly Maëly 2025-05-11T17:39:37Z",
"Cartwight Zhì 2025-06-22T06:27:32Z",
"McNicol Loïc 2026-03-10T16:39:19Z",
"Chander Amélie 2026-04-24T04:41:59Z"
]
*/
You may also use the new Date(), performance differences with Date.parse() are usually negligible, but for very large datasets, precomputing timestamps can help avoid repeated parsing.
Caveats
The compareFn should return:
- A negative value if
ashould come beforeb-
0if they are considered equal- A positive value if
ashould come afterb
If some properties of the objects are missing or do not have the right type you must explicitly handle these cases.
type UserBasic = {
id: number;
firstName: string;
lastName?: string; // This property is optional
email: string;
createdAt: string;
};
userList.toSorted((a, b) => {
// Push undefined/null to the bottom
if (a.lastName === undefined || a.lastName === null) return 1;
if (b.lastName === undefined || b.lastName === null) return -1;
return a.lastName.localeCompare(b.lastName);
});
Conclusion
Sorting arrays of objects is one of those small JavaScript tasks you end up doing everywhere: tables, APIs, search results, analytics, and more...
With modern methods like toSorted(), combined with localeCompare() and a good compareFn, you can build clean, readable, and predictable sorting logic without any third-party library.
About the author
Front-end developer focused on React, Next.js, and clean, scalable CSS. Once building in PHP, Flash and others, now crafting layouts that (mostly) behave as expected. Greg's background in web design (Photoshop, Illustrator) shaped his love for clean layouts and CSS details. This blog is his way of giving back-sharing what he has learned from the same community that keeps inspiring him.
