← Назад к вопросам

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

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Способы сортировки без мутации исходного массива

В современном фронтенд-разработке неизменяемость (immutability) — это ключевой принцип, особенно при работе с такими фреймворками, как React, Vue или Angular, где изменение состояния напрямую может привести к непредсказуемому поведению и сложностям в отладке. Сортировка без мутации означает, что мы создаем новый массив с отсортированными элементами, оставляя исходный массив неизменным. Вот основные способы, которые я использую в своей практике.

1. Использование метода slice() с последующей сортировкой

Самый распространенный подход — создать поверхностную копию массива с помощью slice() или спред-оператора, а затем отсортировать копию. Однако важно помнить, что sort() мутирует массив, к которому применяется, поэтому мы сначала копируем.

const originalArray = [3, 1, 4, 1, 5];
// Создаем копию через slice и сортируем
const sortedArray = originalArray.slice().sort((a, b) => a - b);
console.log(originalArray); // [3, 1, 4, 1, 5] — без изменений
console.log(sortedArray);   // [1, 1, 3, 4, 5] — новый массив

2. Применение спред-оператора (...)

В ES6+ можно использовать спред-оператор для создания копии, что делает код более лаконичным.

const originalArray = ['banana', 'apple', 'cherry'];
const sortedArray = [...originalArray].sort();
console.log(originalArray); // ['banana', 'apple', 'cherry'] — исходный нетронут
console.log(sortedArray);   // ['apple', 'banana', 'cherry']

3. Использование Array.from()

Array.from() создает новый массив из итерируемого объекта, что также подходит для копирования с последующей сортировкой.

const originalArray = [10, 5, 20];
const sortedArray = Array.from(originalArray).sort((a, b) => a - b);
console.log(originalArray); // [10, 5, 20]
console.log(sortedArray);   // [5, 10, 20]

4. Метод concat() для копирования

concat() без аргументов возвращает новую копию массива, которую затем можно отсортировать.

const originalArray = [7, 2, 9];
const sortedArray = originalArray.concat().sort((a, b) => a - b);
console.log(originalArray); // [7, 2, 9]
console.log(sortedArray);   // [2, 7, 9]

5. Функциональный подход с reduce()

Для более сложных сценариев можно использовать reduce(), чтобы построить новый отсортированный массив "с нуля", хотя это менее производительно для простых сортировок.

const originalArray = [4, 2, 8];
const sortedArray = originalArray.reduce((acc, val) => {
  // Вставка в правильную позицию (например, для небольшого массива)
  let i = 0;
  while (i < acc.length && acc[i] < val) i++;
  acc.splice(i, 0, val);
  return acc;
}, []);
console.log(originalArray); // [4, 2, 8]
console.log(sortedArray);   // [2, 4, 8]

6. Сортировка с использованием toSorted() (новый метод ES2023)

В ES2023 появился новый метод toSorted(), который возвращает новый отсортированный массив, не изменяя исходный. Это самый прямой и современный способ.

const originalArray = [5, 3, 9];
const sortedArray = originalArray.toSorted((a, b) => a - b);
console.log(originalArray); // [5, 3, 9] — исходный без изменений
console.log(sortedArray);   // [3, 5, 9] — новый массив

7. Использование библиотечных утилит

В проектах часто используются библиотеки, такие как Lodash, которые предоставляют иммутабельные методы сортировки.

import _ from 'lodash';
const originalArray = [1, 6, 3];
const sortedArray = _.sortBy(originalArray); // Возвращает новый массив
console.log(originalArray); // [1, 6, 3]
console.log(sortedArray);   // [1, 3, 6]

Ключевые моменты для выбора метода:

  • Производительность: Для больших массивов методы slice() или спред-оператор эффективны, так как создают поверхностную копию. reduce() может быть медленнее из-за ручной вставки.
  • Поддержка браузеров: toSorted() — новый метод, который может требовать полифилов для старых браузеров. В production-коде я всегда проверяю поддержку через Can I Use.
  • Глубокая вложенность: Если массив содержит объекты, поверхностное копирование не копирует вложенные структуры. Для глубокой сортировки без мутации может потребоваться рекурсивное клонирование (например, с JSON.parse(JSON.stringify(array)) или библиотеками вроде Lodash).
  • Читаемость кода: В современных проектах я предпочитаю toSorted() или спред-оператор за их явную семантику.

На практике я чаще всего использую спред-оператор или toSorted() (если проект поддерживает ES2023), так как они делают код чистым и выразительным. Важно всегда помнить о принципах иммутабельности в управлении состоянием, особенно при работе с React-приложениями, где это напрямую влияет на оптимизацию ререндеров.