javascript

Методы массивов. Часть 2

  • суббота, 24 января 2026 г. в 00:00:10
https://habr.com/ru/companies/selectel/articles/974326/

Привет, Хабр! Меня зовут Александр Дудукало, я автор курса по JavaScript. Сегодня мы поговорим о ключевом навыке разработчика. С помощью чего сделать код лаконичнее и выразительнее, при этом заменяя громоздкие циклы простыми конструкциями?

Владение методами массивов — это и есть тот самый ответ. Это база, которая позволяет писать код, понятный человеку, а не только машине, и умение переключиться с вопроса «как сделать» на результат «что получить».

Мы разберем три самых полезных метода: map — для преобразования данных, filter — для отбора элементов и sort — для сортировки. Вы поймете, как они работают внутри, и примените знания на практике, создав свои аналоги этих функций. Подробности, как всегда, внутри.

Map — для преобразования элементов массива

Это уже вторая статья о методах массивов JavaScript. Если вы пропустили первую статью, обязательно изучите ее, чтобы разобраться в основах.

Продолжаем разбирать самые полезные методы для работы с массивами. Я считаю, что лучшим способом понять работу любого метода является разбор его кода, а лучше написание своего. Это полезно как для понимания, так и для тренировки. И если говорить о преобразовании данных, то здесь нам идеально подойдет метод map.

Так какую задачу мы решаем? Предлагаю не усложнять. У нас есть массив объектов учеников школы с их именами и возрастом. Нам нужно на его основе создать новый массив, где каждый элемент будет строкой вида: «Имя: Оля, возраст: 17».

Пишем свою функцию myMap:

function myMap(array, fn) {
 const result = [];
 for (let i = 0; i < array.length; i++) {
   result.push(fn(array[i], i, array));
 }

 return result;
}

const students = [
 { name: 'Оля', age: 17 },
 { name: 'Петя', age: 16 },
 { name: 'Анна', age: 18 },
 { name: 'Иван', age: 17 },
 { name: 'Мария', age: 16 }
];

const studentStrings = myMap(students, function(student) {
 return Имя: ${student.name}, возраст: ${student.age};
});

console.log(studentStrings);
Результат в консоли.
Результат в консоли.

Готово! Наша функция успешно решила задачу. Она принимает данные и callback-функцию. Далее применяет ее к каждому элементу исходного массива с помощью цикла. И в итоге возвращает новый список с результатами, не меняя старый. А главное — она универсальна. Ее можно применять к любому массиву под разные задачи.

Именно такую логику преобразования каждого элемента и создания нового массива и реализует стандартный метод map. Синтаксис становится гораздо лаконичнее, а суть остается той же. Смотрим:

const students = [
 { name: 'Оля', age: 17 },
 { name: 'Петя', age: 16 },
 { name: 'Анна', age: 18 },
 { name: 'Иван', age: 17 },
 { name: 'Мария', age: 16 }
];

const studentStrings = students.map(function(student) {
 return Имя: ${student.name}, возраст: ${student.age};
});

console.log(studentStrings);
Результат в консоли.
Результат в консоли.

Все просто и наглядно, согласны? Главное, исходный массив students остался неизменным, а мы получили новый массив studentStrings.

Теперь можно дать определение методу map.

map — это метод массива, который создает его новую копию, применяя переданную функцию к каждому элементу исходного массива.

Принимает: callback-функцию, вызываемую для каждого элемента. 

Эта функция может принимать три аргумента:

  • currentValue — текущий обрабатываемый элемент;

  • index (необязательно) — индекс этого элемента;

  • array (необязательно) — исходный массив.

Возвращает: новый массив той же длины, состоящий из результатов вызова callback-функции на каждом элементе. Исходный массив не изменяется.

Используйте map, например, чтобы извлечь данные или изменить формат. Метод просто создаст видоизмененную копию исходного массива.

Бесплатный базовый курс по JS

Рассказываем, как работать с переменными, типами данных, функциями и о многом другом!

Старт в январе →

Filter — убрать лишнее и оставить нужное

Скажу сразу: фильтрация — одна из самых частых задач при работе с массивами. Если вам нужно отсеять элементы по какому-либо условию и получить новый массив только с подходящими, то метод filter — ваш лучший помощник. Кстати, его можно использовать даже для удаления конкретного элемента (но, об этом позже).

Как и в прошлый раз с map, лучший способ разобраться — это написать свою упрощенную версию. Давайте создадим функцию, которая отфильтрует несовершеннолетних пользователей. То есть оставит только тех, чей возраст ≥ 18 лет.

function myFilter(array, fn) {
 const result = [];
 for (let i = 0; i < array.length; i++) {
   if (fn(array[i], i, array)) {
     result.push(array[i]);
   }
 }

 return result;
}

const users = [
 { name: "Оля", age: 17 },
 { name: "Петя", age: 20 },
 { name: "Анна", age: 15 },
 { name: "Иван", age: 18 },
 { name: "Мария", age: 22 },
];

const adultUsers = myFilter(users, function (user) {
 return user.age >= 18;
});

console.log(adultUsers);
Результат в консоли.
Результат в консоли.

Отлично, наша функция работает. Она принимает массив и функцию-условие (callback-функцию). Далее проверяет каждый элемент этим условием, проходит по массиву и в итоге возвращает новый. В него попадут только те элементы, для которых условие вернуло true.

В общем, вся суть функции myFilter заключена в передаваемой функции-условии, ее еще называют предикатом. Именно она «решает» судьбу каждого элемента: пропустить его в новый массив или отфильтровать. Это позволяет гибко настраивать отбор под самые разные задачи.

Ну а теперь немного практики, заменим нашу самописную функцию на встроенный метод, который уже есть в JavaScript:

const users = [
 { name: "Оля", age: 17 },
 { name: "Петя", age: 20 },
 { name: "Анна", age: 15 },
 { name: "Иван", age: 18 },
 { name: "Мария", age: 22 },
];

const adultUsers = users.filter(function (user) {
 return user.age >= 18;
});

console.log(adultUsers);
Результат в консоли.
Результат в консоли.

И все работает. Исходный массив users остался цел, а мы получили новый — adultUsers.

Кстати, для новичка такие конструкции с callback-функцией внутри метода могут сначала казаться немного громоздкими. Но не переживайте, это нормально. Чуть больше практики, и вы будете читать этот код как обычное предложение. А теперь перейдем к определению.

filter — это метод, который создает новую копию и содержит только те элементы исходного массива, для которых переданная функция-условие возвращает true.

Принимает: обязательный параметр callback-функцию (условие). 

Эта функция вызывается для каждого элемента массива и может принимать три аргумента:

  • currentValue — текущий элемент;

  • index (необязательно) — индекс этого элемента;

  • array (необязательно) — исходный массив.

Возвращает: новый массив, состоящий только из элементов, прошедших проверку. Если ни один элемент не соответствует условию, возвращается пустой массив [], при этом исходный не изменяется.

Используйте filter, когда вам нужно отобрать элементы из массива по какому-либо признаку. Метод не меняет исходный массив, что гарантирует безопасность ваших данных. Он хорошо подходит для фильтрации списков товаров, пользователей или любых данных по условию.

Sort — сортировка элементов это просто

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

Сортировка в коде встречается гораздо чаще, чем можно подумать. И дело не только в каталогах интернет-магазинов. Любой список контактов, таблица с данными, даже комментарии по дате — везде нужна сортировка. И очень удобно, что в JavaScript для этого есть готовый встроенный метод.

Давайте сначала напишем свою упрощенную функцию сортировки, чтобы понять логику. Внимание, этот алгоритм будет сложнее предыдущих. Один из самых простых для понимания — «Сортировка пузырьком». Как он работает, можно посмотреть в моем видео, а мы опишем его кодом с помощью двух вложенных циклов. Кстати, алгоритмов сортировки много, и их самостоятельное изучение будет большим плюсом.

По аналогии с myMap и myFilter напишем функцию mySort, которая будет принимать массив и callback-функцию: 

function mySort(array, fn) {

 // Внешний цикл: проходит по всем элементам
 for (let i = 0; i < array.length; i++) {

   // Внутренний цикл: сравнивает соседние элементы
   for (let j = 0; j < array.length - 1 - i; j++) {

     // Если результат сравнения больше 0, меняем элементы местами
     if (fn(array[j], array[j + 1]) > 0) {
       const temp = array[j];
       array[j] = array[j + 1];
       array[j + 1] = temp;
     }
   }
 }

 return array;
}

const users = [
 { name: "Оля", age: 17 },
 { name: "Петя", age: 20 },
 { name: "Анна", age: 15 },
 { name: "Иван", age: 18 },
 { name: "Мария", age: 22 },
];

// Пример 1: Сортировка по возрасту (по возрастанию)
const sortedByAge = mySort([...users], function (a, b) {
 return a.age - b.age; // Если результат > 0, элементы поменяются местами
});

// Пример 2: Сортировка по возрасту (по убыванию)
const sortedByAge2 = mySort([...users], function (a, b) {
 return b.age - a.age; // Если результат > 0, элементы поменяются местами
});

console.log("По возрастанию", sortedByAge);

console.log("По убыванию", sortedByAge2);
Результат в консоли.
Результат в консоли.

Если коротко, то передаваемая callback-функция получает два элемента массива a и b. Затем функция возвращает число:

  • меньше 0 — a должен быть перед b (элементы остаются как есть);

  • больше 0 — a должен быть после b (элементы меняются местами);

  • равно 0 — порядок не важен.

Для чисел чаще всего используют a - b (сортировка по возрастанию) или b - a (по убыванию). Таким образом, на основе результата выполнения этой функции в цикле принимается решение стоит менять элементы местами или нет.

Кстати, обратите внимание, для создания копии массива я использую синтаксис rest, о котором уже рассказал в этой статье. Это нужно сделать для избежания сортировки исходного массива, так как наша функция является мутирующей (меняет исходные данные).

Своя функция — хорошо, но готовая лучше. Смотрим пример работы встроенного метода сортировки:

const users = [
 { name: "Оля", age: 17 },
 { name: "Петя", age: 20 },
 { name: "Анна", age: 15 },
 { name: "Иван", age: 18 },
 { name: "Мария", age: 22 },
];

// Пример 1: Сортировка по возрасту (по возрастанию)
const sortedByAge = [...users].sort(function (a, b) {
 return a.age - b.age; // Если результат > 0, элементы поменяются местами
});

// Пример 2: Сортировка по возрасту (по убыванию)
const sortedByAge2 = [...users].sort(function (a, b) {
 return b.age - a.age; // Если результат > 0, элементы поменяются местами
});

console.log("По возрастанию", sortedByAge);
console.log("По убыванию", sortedByAge2);
Результат в консоли.
Результат в консоли.

Эффект тот же, но кода стало меньше. Нам не пришлось писать алгоритм сортировки самим. 

sort — это метод массива, который сортирует его элементы (мутирует исходный) и возвращает отсортированный массив.

Принимает: необязательную функцию-компаратор. Если функция не передана, элементы приводятся к строкам и сортируются по порядку Unicode.

Функция-компаратор должна возвращать число, которое определяет порядок элементов:

  • отрицательное число (<0) — a ставится перед b;

  • положительное число (>0) — a ставится после b;

  • ноль (=== 0) — порядок a и b не меняется.

Возвращает: тот же самый массив, но отсортированный. Из-за мутации рекомендуется работать с копией, если нужно сохранить исходный порядок.

По умолчанию сортирует элементы как строки, что для чисел требует передачи функции-компаратора.

Так что используйте sort, когда нужно упорядочить элементы массива по какому-либо критерию: числа по возрастанию, строки по алфавиту, объекты по дате. Всегда создавайте копию, например, через [...arr].sort(...), если оригинальный порядок нужно сохранить для дальнейшей работы.

Подведем итог

Вы освоили три основных метода массивов: map для преобразования данных, filter для отбора и sort для сортировки. Теперь вы понимаете не только как их использовать, но и как они работают внутри.

Эти методы — ваши главные инструменты для работы с данными. Они делают код чище, понятнее и короче, заменяя громоздкие циклы одной выразительной строкой. Главное — они создают новые массивы, сохраняя исходные данные в безопасности (кроме sort, где нужно помнить о копировании).

Начинайте применять их на практике сразу же. Попробуйте в следующих задачах заменить циклы на эти методы, и вы быстро почувствуете, насколько эффективнее и удобнее становится ваш код.