Какие могут быть проблемы при сортировке с параметризуемым методом в JavaScript?

«Какие могут быть проблемы при сортировке с параметризуемым методом в JavaScript?» — вопрос из категории Алгоритмы и структуры данных, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При использовании Array.prototype.sort(compareFunction) в Node.js (и JavaScript в целом) можно столкнуться со следующими проблемами:

  1. Мутация исходного массива: Метод sort() изменяет исходный массив, что может привести к трудноуловимым багам.

    const original = [3, 1, 2];
    const sorted = original.sort(); // original теперь тоже [1, 2, 3]!
    console.log(original); // [1, 2, 3]
    // Решение: создать копию
    const safeSorted = [...original].sort();
  2. Некорректная функция сравнения по умолчанию: Без функции сравнения элементы преобразуются в строки и сортируются лексикографически, что даёт неожиданный результат для чисел.

    console.log([10, 2, 1].sort()); // [1, 10, 2] - неверно для чисел
    console.log([10, 2, 1].sort((a, b) => a - b)); // [1, 2, 10] - верно
  3. Нарушение контракта compareFunction: Функция должна возвращать число: отрицательное, ноль или положительное. Возврат булевых значений (true/false) — распространённая ошибка.

    // НЕВЕРНО: Возвращает boolean
    [1, 3, 2].sort((a, b) => a > b); // Поведение может различаться в разных движках
    // ВЕРНО: Возвращает number
    [1, 3, 2].sort((a, b) => a - b); // Гарантированно корректно
  4. Сложность сортировки объектов: Необходимо явно указывать поле для сравнения.

    const users = [{ name: 'Bob', age: 30 }, { name: 'Alice', age: 25 }];
    users.sort((a, b) => a.age - b.age); // Сортировка по возрасту
  5. Производительность для больших массивов: Неоптимальный алгоритм внутри compareFunction может стать узким местом. Для сложных сортировок иногда эффективнее предварительно подготовить данные (например, вычислить ключ сортировки один раз для каждого элемента).

  6. Проблемы с локалью и символами Unicode: Для строковой сортировки с учётом локали используйте String.prototype.localeCompare().

    const items = ['réservé', 'premier', 'cliché'];
    items.sort((a, b) => a.localeCompare(b, 'en'));