Сортировка массива объектов по строке: 5 способов для JavaScript

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Сортировка массива объектов по строковому свойству: разбираем популярный вопрос с Stack Overflow

Представьте: у вас есть список пользователей, товаров или статей. Каждый элемент — это объект с кучей свойств: имя, цена, дата, рейтинг. И вам нужно отсортировать всё это, скажем, по фамилии в алфавитном порядке. Задача, которая кажется простой, но на практике подкидывает сюрпризы. Неудивительно, что вопрос "Sort array of objects by string property value" на Stack Overflow собрал тысячи просмотров и десятки ответов.

В этой статье мы не просто дадим готовый код. Мы разберём 5 способов сортировки, от базового до продвинутого, выявим типичные грабли и покажем, как их обойти. К концу вы сможете сортировать любые данные одной левой.

Что такое сортировка массива объектов в JavaScript?

В JavaScript есть встроенный метод Array.prototype.sort(). Но с объектами он работает неочевидно. Если вызвать sort() без аргументов, он попытается сравнивать элементы как строки. Для чисел это даёт сюрприз: [1, 20, 3].sort() вернёт [1, 20, 3], а не [1, 3, 20]. Для объектов — полный хаос.

Поэтому нам нужна функция сравнения (comparator). Она принимает два элемента и возвращает:

  • отрицательное число, если первый элемент меньше второго;
  • 0, если равны;
  • положительное число, если первый больше.

Вот базовая структура сортировки массива объектов по строковому свойству:

// Исходный массив
const users = [
    { name: 'Иван', age: 25 },
    { name: 'Анна', age: 30 },
    { name: 'Борис', age: 22 }
];

// Сортировка по полю name
users.sort((a, b) => {
    if (a.name < b.name) return -1;
    if (a.name > b.name) return 1;
    return 0;
});

console.log(users);
// [{ name: 'Анна', age: 30 }, { name: 'Борис', age: 22 }, { name: 'Иван', age: 25 }]

Этот код работает, но он громоздкий. Давайте посмотрим, как сделать его элегантнее.

5 способов отсортировать массив объектов по строке

Способ 1: Классическая функция сравнения

Самый прозрачный метод. Подходит для любых строк, включая кириллицу, при условии, что вы используете правильный алфавитный порядок. Сравнение через < и > учитывает коды символов в Unicode, что для русского языка даёт неожиданный результат: «ё» окажется в конце алфавита, а «я» — рядом с «а».

const products = [
    { title: 'Яблоко', price: 50 },
    { title: 'Ёлка', price: 200 },
    { title: 'Ананас', price: 150 }
];

// Проблема: 'Ёлка' встанет после 'Яблоко'
products.sort((a, b) => {
    if (a.title < b.title) return -1;
    if (a.title > b.title) return 1;
    return 0;
});

Когда использовать: для английских строк, где алфавитный порядок совпадает с Unicode.

Способ 2: localeCompare — спаситель кириллицы

Метод String.prototype.localeCompare() учитывает правила сортировки для конкретного языка. Для русского — передаём 'ru'.

users.sort((a, b) => a.name.localeCompare(b.name, 'ru'));

console.log(users);
// [{ name: 'Анна', age: 30 }, { name: 'Борис', age: 22 }, { name: 'Иван', age: 25 }]

Этот код чище, короче и правильно обрабатывает «ё», «й» и другие буквы. Если нужно отсортировать по убыванию — просто поменяйте местами a и b:

users.sort((a, b) => b.name.localeCompare(a.name, 'ru'));

Когда использовать: всегда, когда работаете с кириллицей или многоязычными данными.

Способ 3: Сортировка с учётом регистра

По умолчанию localeCompare чувствителен к регистру: «apple» встанет перед «Banana», потому что строчная буква имеет больший Unicode-код. Если нужно игнорировать регистр, добавьте опцию { sensitivity: 'base' }.

const mixed = [
    { name: 'apple' },
    { name: 'Banana' },
    { name: 'Apple' }
];

// Без опции: Banana, Apple, apple
mixed.sort((a, b) => a.name.localeCompare(b.name));

// С опцией: apple, Apple, Banana (регистр не важен)
mixed.sort((a, b) => a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }));

Способ 4: Сортировка по вложенным свойствам

Часто объекты имеют вложенную структуру. Например, у пользователя есть адрес с городом. Как отсортировать по городу?

const people = [
    { name: 'Иван', address: { city: 'Москва' } },
    { name: 'Анна', address: { city: 'Астрахань' } },
    { name: 'Борис', address: { city: 'Волгоград' } }
];

people.sort((a, b) => a.address.city.localeCompare(b.address.city, 'ru'));

console.log(people);
// Анна (Астрахань), Борис (Волгоград), Иван (Москва)

Если свойство может отсутствовать, добавьте проверку:

people.sort((a, b) => {
    const cityA = a.address?.city || '';
    const cityB = b.address?.city || '';
    return cityA.localeCompare(cityB, 'ru');
});

Способ 5: Динамическая сортировка по любому свойству

А что, если пользователь сам выбирает поле для сортировки? Создадим универсальную функцию:

function sortByProperty(arr, prop, locale = 'ru') {
    return arr.sort((a, b) => {
        const valA = a[prop] || '';
        const valB = b[prop] || '';
        return valA.localeCompare(valB, locale);
    });
}

// Пример использования
const sortedByName = sortByProperty(users, 'name');
const sortedByTitle = sortByProperty(products, 'title');

Совет: Для обратной сортировки передавайте флаг desc и меняйте порядок a и b.

Частые вопросы (FAQ) по сортировке объектов в JavaScript

Почему sort() без аргументов не работает для чисел?

Потому что sort() преобразует элементы в строки. [1, 20, 3].sort() даёт [1, 20, 3], так как

Блоги

Рекомендаций по книгам