Какие знаешь способы сделать сортировку без мутации?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы сортировки без мутации исходного массива
В современном фронтенд-разработке неизменяемость (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-приложениями, где это напрямую влияет на оптимизацию ререндеров.