Урок 18: Методы массивов высшего порядка в JavaScript’е

Если вы дошли до этого урока, то уже знаете, что такое массивы, циклы и функции. Теперь пришло время вывести ваши навыки на новый уровень. Мы погрузимся в методы .map().filter() и .reduce(). Научимся комбинировать их и решать сложные задачи элегантно и эффективно.

Почему это важно? Потому что эти методы основа функционального программирования в JavaScript. Они делают код чище, короче и понятнее.

Что такое методы высшего порядка?

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

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

Метод .map(): Преобразование данных

Ситуация: У вас есть массив чисел, и вам нужно создать новый массив, где каждое число умножено на 2.
Раньше вы бы использовали цикл for, но сегодня научимся делать это в одну строку.

Как работает .map():

  • Принимает callback-функцию.
  • Вызывает эту функцию для каждого элемента массива.
  • Возвращает новый массив с результатами вызовов.

Пример:

const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]

Разберем по шагам:

  1. numbers — исходный массив.
  2. .map() проходит по каждому элементу.
  3. num => num * 2 — стрелочная функция, которая умножает элемент на 2.
  4. Результат сохраняется в новый массив doubled.

Где это пригодится:

  • Преобразование данных из API (например, извлечение имен пользователей).
  • Форматирование строк (добавление символов, изменение регистра).

Задача 1:
Дан массив температур в градусах Цельсия: [0, 15, 25, -5]. Преобразуйте их в градусы Фаренгейта по формуле: F = C * 1.8 + 32.

Решение:

const celsius = [0, 15, 25, -5];
const fahrenheit = celsius.map(c => c * 1.8 + 32);
console.log(fahrenheit); // [32, 59, 77, 23]

Метод .filter(): Фильтрация элементов

Ситуация: У вас есть массив пользователей, и вам нужно выбрать только тех, кто старше 18 лет.

Как работает .filter():

  • Принимает callback-функцию, которая возвращает true или false.
  • Создает новый массив из элементов, для которых callback вернул true.

Пример:

const ages = [12, 25, 8, 30, 17];
const adults = ages.filter(age => age >= 18);
console.log(adults); // [25, 30]

Разбор:

  • age >= 18 — условие фильтрации.
  • В новый массив adults попадают только элементы, удовлетворяющие условию.

Где это пригодится:

  • Поиск элементов по критериям (например, товары определенной категории).
  • Удаление «мусора» из данных (пустые строки, нули).

Задача 2:
Дан массив строк: ['JavaScript', 'Python', 'C++', 'Java', '', 'Ruby']. Отфильтруйте пустые строки и языки с длиной названия больше 4 символов.

Решение:

const languages = ['JavaScript', 'Python', 'C++', 'Java', '', 'Ruby'];
const filtered = languages.filter(lang => lang !== '' && lang.length > 4);
console.log(filtered); // ['JavaScript', 'Python']

Метод .reduce(): Агрегация данных

Ситуация: Вам нужно вычислить сумму всех элементов массива, найти максимальное значение или объединить элементы в строку.

Как работает .reduce():

  • Принимает callback-функцию и начальное значение аккумулятора (опционально).
  • Callback получает аккумулятор (промежуточный результат) и текущий элемент.
  • Возвращает финальное значение аккумулятора.

Пример: Сумма элементов

const numbers = [10, 20, 30];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 60

Разберем аргументы:

  • (acc, num) => acc + num — функция, которая прибавляет текущий элемент к аккумулятору.
  • 0 — начальное значение аккумулятора.

Где это пригодится:

  • Вычисление статистики (среднее, сумма, максимум).
  • Преобразование массива в объект (например, группировка по категориям).

Задача 3:
Дан массив слов: ['functional', 'programming', 'is', 'awesome']. Используйте .reduce(), чтобы объединить их в одну строку через пробел.

Решение:

const words = ['functional', 'programming', 'is', 'awesome'];
const sentence = words.reduce((acc, word) => acc + ' ' + word, '').trim();
console.log(sentence); // "functional programming is awesome"

Комбинирование методов

Вот где начинается магия! Методы можно объединять в цепочки для решения сложных задач.

Пример:
У вас есть массив товаров:

const products = [
  { name: 'Laptop', price: 1000, category: 'electronics' },
  { name: 'Shirt', price: 20, category: 'clothes' },
  { name: 'Phone', price: 500, category: 'electronics' },
  { name: 'Socks', price: 5, category: 'clothes' },
];

Задача:
Вычислить общую стоимость всех электронных товаров.

Решение:

const total = products
  .filter(product => product.category === 'electronics') // Фильтруем
  .map(product => product.price) // Извлекаем цены
  .reduce((acc, price) => acc + price, 0); // Суммируем

console.log(total); // 1500

Разбор:

  1. .filter() оставляет только электронику.
  2. .map() создает массив цен.
  3. .reduce() складывает цены.

Практические задачи

Закрепим знания на реальных примерах.

Задача 1: Рейтинг книг

Дан массив книг:

const books = [
  { title: '1984', rating: 4.8, pages: 328 },
  { title: 'Brave New World', rating: 4.0, pages: 288 },
  { title: 'Fahrenheit 451', rating: 4.5, pages: 227 },
];

Цель: Получить массив названий книг с рейтингом выше 4.3.

Используйте цепочку .filter() и .map(). 

Задача 2: Самый длинный комментарий

Дан массив комментариев:

const comments = [
  { text: 'Cool!', likes: 15 },
  { text: 'Awesome article', likes: 23 },
  { text: 'Thanks!', likes: 5 },
];

Цель: Найти комментарий с максимальным количеством лайков, используя .reduce().

Задача 2: Группировка по первым буквам

Дан массив имен: ['Alice', 'Bob', 'Anna', 'Charlie', 'Alex'].
Цель: Создать объект, где ключи — первые буквы имен, а значения — массивы имен.

Пример результата:

{
  A: ['Alice', 'Anna', 'Alex'],
  B: ['Bob'],
  C: ['Charlie']
}

Используйте .reduce() с аккумулятором-объектом.

Частые ошибки

  1. Забыли return в callback-функции:
    Стрелочные функции с фигурными скобками требуют явного return.

    // Ошибка:
    arr.map(num => { num * 2 }); // Вернет [undefined, undefined...]
    // Правильно:
    arr.map(num => num * 2); // Или { return num * 2; }
  2. Использование методов для side effects:
    .map().filter().reduce() не должны изменять внешние переменные.

Сегодня вы сделали огромный шаг в освоении JavaScript. Методы высшего порядка это инструменты, которые сделают ваш код профессиональным и лаконичным. Практикуйтесь, решайте задачи и комбинируйте методы.

Полный курс «JavaScript для начинающих» доступен здесь: https://max-gabov.ru/javascript-dlya-nachinaushih.