Сортировка — это перестановка элементов набора в заданном порядке: по возрастанию (от меньшего к большему) или по убыванию (от большего к меньшему). Ниже разберем, как сделать это в JavaScript методом sort с функцией сравнения (компаратором) и его иммутабельным аналогом toSorted, а в Excel — формулой СОРТ и кнопками А-Я / Я-А. Отдельно покажем главную ловушку JavaScript: sort без компаратора сортирует числа как строки.
Содержание
Ловушка: sort без компаратора сортирует числа как текст
Первое, обо что спотыкаются новички: у массива чисел вызывают sort() без аргументов и ждут числовой порядок. Метод Array.prototype.sort по умолчанию приводит элементы к строкам и сравнивает их посимвольно (лексикографически). Поэтому "10" оказывается раньше "2", ведь символ 1 меньше символа 2.
Неверный код:
console.log([1, 2, 10, 21, 100].sort());
Фактический результат (проверено в Node.js 22):
[ 1, 10, 100, 2, 21 ]
Порядок сломан: 10 и 100 встали перед 2. Исправление — передать в sort функцию сравнения (компаратор), которая сравнивает числа как числа:
// по возрастанию: a - b
console.log([1, 2, 10, 21, 100].sort((a, b) => a - b));
[ 1, 2, 10, 21, 100 ]
Правило простое: для чисел компаратор в sort обязателен. Для сортировки строк компаратор не нужен, но лексикографический порядок там как раз уместен (учет регистра и алфавита — отдельная тема, см. ниже про localeCompare).
Как работает компаратор
Компаратор — это функция двух аргументов (a, b), которая возвращает число:
- отрицательное —
aидет раньшеb; - положительное —
aидет позжеb; - ноль — порядок
aиbне меняется относительно друг друга.
Выражение a - b дает отрицательное значение, когда a < b, значит меньшие числа встают в начало — это возрастание. Чтобы получить убывание, достаточно поменять операнды местами:
// по убыванию: b - a
console.log([1, 2, 10, 21, 100].sort((a, b) => b - a));
[ 100, 21, 10, 2, 1 ]
Важно: возвращать нужно любое число нужного знака, а не строго 1, 0 и -1. Приемы вида a - b работают именно потому, что знак разности и есть ответ компаратора. Для строк такой трюк не подходит — вычитать строки нельзя, там применяют localeCompare (о нем ниже).
Мутирующий sort и иммутабельный toSorted
Ключевое различие, о котором забывают: sort меняет исходный массив на месте и возвращает ссылку на него же. Отдельной копии не возникает.
const nums = [3, 1, 2];
const sorted = nums.sort((a, b) => a - b);
console.log(nums, sorted, nums === sorted);
[ 1, 2, 3 ] [ 1, 2, 3 ] true
Исходный nums уже отсортирован, а sorted — та же самая ссылка (nums === sorted дает true). Если исходный порядок нужно сохранить, это баг.
Начиная со стандарта ES2023 (Node.js 20+ и современные браузеры) есть метод toSorted — он возвращает новый отсортированный массив, не трогая исходный:
const orig = [3, 1, 2];
const copy = orig.toSorted((a, b) => a - b);
console.log(orig, copy, orig === copy);
[ 3, 1, 2 ] [ 1, 2, 3 ] false
orig остался прежним, copy — новый массив (orig === copy дает false). Если поддержка toSorted в целевой среде под вопросом, тот же эффект дает копия перед сортировкой: [...orig].sort((a, b) => a - b).
Сортировка массива объектов по полю
На практике чаще сортируют не голые числа, а объекты по одному из полей. Компаратор просто обращается к нужному свойству:
const users = [
{ name: "Anna", age: 30 },
{ name: "Boris", age: 25 },
{ name: "Vera", age: 41 },
];
const byAge = users.toSorted((a, b) => a.age - b.age);
console.log(byAge.map((u) => `${u.name}:${u.age}`).join(", "));
Boris:25, Anna:30, Vera:41
Для сортировки по строковому полю (например, по имени) вместо вычитания используют localeCompare — он учитывает алфавит конкретного языка:
const names = ["Ваня", "Аня", "Боря"];
console.log(names.sort((a, b) => a.localeCompare(b, "ru")));
[ 'Аня', 'Боря', 'Ваня' ]
Для убывания по строке результат localeCompare умножают на -1: (a, b) => b.localeCompare(a, "ru").
Сортировка в Excel: формула СОРТ и кнопки
В Excel сортировка чисел по возрастанию и убыванию делается тремя способами, и логика та же, что в JavaScript, — меняется только направление.
Кнопки. Выделите диапазон, вкладка «Главная» — «Редактирование» — «Сортировка и фильтр». Пункт «По возрастанию» (А-Я) выстраивает от меньшего к большему, «По убыванию» (Я-А) — наоборот. Для чисел, в отличие от JavaScript, отдельный компаратор не нужен: Excel сам определяет тип данных и сортирует числа как числа.
Настраиваемая сортировка. Тот же путь, пункт «Настраиваемая сортировка»: можно задать несколько уровней (столбцов) кнопкой «Добавить уровень» — сначала по одному полю, при равенстве по второму. В колонке «Порядок» выбирается «По возрастанию» или «По убыванию».
Формула СОРТ (SORT). В версиях с динамическими массивами (Microsoft 365 и Excel 2021+) есть формула, которая сортирует диапазон без изменения исходных данных и пересчитывается автоматически:
=СОРТ(A1:A10)— по возрастанию (третий аргумент по умолчанию1);=СОРТ(A1:A10;1;-1)— по убыванию (третий аргумент-1);=СОРТПО(A1:A10;B1:B10;-1)— сортирует диапазонAпо ключу из диапазонаBпо убыванию.
Старые функции =НАИМЕНЬШИЙ(диапазон;k) и =НАИБОЛЬШИЙ(диапазон;k) возвращают k-е по величине значение и позволяли имитировать сортировку до появления СОРТ; в актуальных версиях удобнее СОРТ.
JavaScript и Excel: чем отличается сортировка
| Свойство | JavaScript | Excel |
|---|---|---|
| Числа по возрастанию | arr.sort((a, b) => a - b) |
кнопка А-Я или =СОРТ(диапазон) |
| Числа по убыванию | arr.sort((a, b) => b - a) |
кнопка Я-А или =СОРТ(диапазон;1;-1) |
| Числа без явного порядка | сортируются как строки (нужен компаратор) | сортируются как числа автоматически |
| Меняет исходные данные | sort — да, toSorted — нет |
кнопки — да, формула СОРТ — нет |
| Сортировка по нескольким ключам | несколько сравнений в компараторе | «Добавить уровень» или СОРТПО |
| Строки/алфавит | localeCompare(a, b, "ru") |
по правилам локали автоматически |
Главное отличие для новичка: в Excel числа по умолчанию сортируются как числа, а в JavaScript sort без компаратора трактует их как строки. Отсюда и разница в результате [1, 2, 10].
Выводы
- В JavaScript для чисел компаратор в
sortобязателен: без него[1, 2, 10].sort()дает[1, 10, 2], потому что элементы сравниваются как строки. - Возрастание —
(a, b) => a - b, убывание —(a, b) => b - a; знак разности и есть ответ компаратора. sortмутирует исходный массив и возвращает ссылку на него;toSorted(ES2023, Node.js 20+) возвращает новый массив, не трогая исходный.- Объекты сортируют по полю (
a.age - b.age), строки — черезlocaleCompare, а не вычитанием. - В Excel числа сортируются как числа сразу: кнопки А-Я / Я-А, «Настраиваемая сортировка» для нескольких уровней и формула СОРТ (СОРТ;1;-1 для убывания), которая не меняет исходные данные.
Где применяется / связь с практикой
Сортировка — базовая операция в почти любом коде на JavaScript: вывод товаров по цене, задач по дате, пользователей по имени, рейтингов по убыванию. Понимание разницы между sort и toSorted и привычка всегда писать компаратор для чисел избавляют от целого класса плавающих багов, когда список «иногда» упорядочен неверно.
Освойте тему на практике
Разобраться с массивами, методами sort/toSorted, коллбэками и остальной базой языка системно помогает курс JavaScript Basic: там сортировка разбирается на реальных задачах, а не на изолированных примерах. Посмотреть формат занятий и темы можно на открытых уроках Otus — вход бесплатный.
FAQ
Почему [1, 2, 10].sort() возвращает [1, 10, 2]?
Потому что sort без аргументов приводит элементы к строкам и сравнивает посимвольно: символ 1 меньше символа 2, поэтому "10" встает раньше "2". Для чисел нужен компаратор (a, b) => a - b.
Чем toSorted отличается от sort и когда его брать?
sort меняет исходный массив на месте, toSorted возвращает новую отсортированную копию и оставляет исходный нетронутым. Берите toSorted, когда исходный порядок нужно сохранить (например, массив пришел из стороннего кода или состояния приложения).
Как в Excel отсортировать по одному столбцу, а при равенстве — по второму?
Через «Настраиваемая сортировка»: добавьте первый уровень по основному столбцу, затем «Добавить уровень» и укажите второй столбец. Или формулой СОРТПО с несколькими массивами-ключами.



