Как отсортировать массив объектов по строковому свойству в JavaScript?
Правильный способ сортировки массива объектов по строковому свойству
Проблема в вашем коде в том, что метод sort() ожидает от функции сравнения возврата числа (отрицательного, нуля или положительного), а не булева значения. Оператор - работает только с числами, а для строк нужно использовать метод localeCompare() или прямое сравнение через if-else.
Решение 1: Использование localeCompare() (рекомендуется)
Метод localeCompare() сравнивает две строки с учётом локали и возвращает число — идеально подходит для sort():
const users = [
{ name: 'Иван', age: 25 },
{ name: 'Петр', age: 30 },
{ name: 'Анна', age: 22 },
{ name: 'Мария', age: 28 }
];
users.sort((a, b) => a.name.localeCompare(b.name));
console.log(users);
// Результат:
// [
// { name: 'Анна', age: 22 },
// { name: 'Иван', age: 25 },
// { name: 'Мария', age: 28 },
// { name: 'Петр', age: 30 }
// ]
Решение 2: Ручное сравнение строк
Если по какой-то причине вы не можете использовать localeCompare(), можно реализовать сравнение вручную:
users.sort((a, b) => {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
});
Как работает функция сравнения в sort()?
- Функция получает два элемента массива (a и b).
- Если возвращаемое значение < 0, a ставится перед b.
- Если возвращаемое значение > 0, b ставится перед a.
- Если возвращаемое значение = 0, порядок не меняется.
Важные замечания
- Мутация массива: Метод
sort()изменяет исходный массив. Если нужно сохранить оригинал, сделайте копию:const sorted = [...users].sort(...). - Регистр:
localeCompare()по умолчанию учитывает регистр — 'Анна' будет перед 'иван'. Для регистронезависимой сортировки используйтеa.name.localeCompare(b.name, undefined, {sensitivity: 'base'}). - Сортировка по убыванию: Просто поменяйте местами a и b:
b.name.localeCompare(a.name).
Пример с дополнительными опциями
// Сортировка по убыванию с игнорированием регистра
users.sort((a, b) => b.name.localeCompare(a.name, undefined, { sensitivity: 'base' }));
Теперь ваш массив будет отсортирован правильно! Используйте localeCompare() — это самый надёжный и гибкий способ для строк.
Альтернативный подход: Использование String.prototype.localeCompare() с учётом числовых свойств
Если в вашем массиве объектов есть не только строковые, но и числовые свойства, и вы хотите сортировать по строке, но при равенстве строк — по числу, можно объединить условия:
const people = [
{ name: 'Иван', age: 25 },
{ name: 'Анна', age: 30 },
{ name: 'Анна', age: 22 }
];
people.sort((a, b) => {
const nameCompare = a.name.localeCompare(b.name);
if (nameCompare !== 0) return nameCompare;
return a.age - b.age; // если имена равны, сортируем по возрасту
});
console.log(people);
// [
// { name: 'Анна', age: 22 },
// { name: 'Анна', age: 30 },
// { name: 'Иван', age: 25 }
// ]
Для обратной совместимости (старые браузеры)
Метод localeCompare() поддерживается всеми современными браузерами, но если вам нужно поддерживать очень старые версии (например, Internet Explorer < 11), можно использовать ручное сравнение строк через < и > как показано в первом ответе.
Совет по производительности
Для больших массивов (10 000+ элементов) избегайте сложных операций внутри функции сравнения. Если возможно, предварительно преобразуйте строки в нижний регистр и сохраните в отдельном поле для ускорения:
const prepared = users.map(u => ({ ...u, _sortKey: u.name.toLowerCase() }));
prepared.sort((a, b) => a._sortKey.localeCompare(b._sortKey));
Этот подход минимизирует вызовы toLowerCase() внутри функции сравнения.
Ответов пока нет.
Войдите чтобы оставить ответ