Перейти к содержимому
Тема 11 из 16
Теория

Методы массивов

Зачем это нужно

В прошлой теме мы перебирали массивы циклами. Это работает, но код получается длинным: завести пустой массив, цикл, условие, push… У массивов есть методы, которые делают типичные вещи одной строкой: «преобразуй каждый элемент», «оставь только подходящие», «посчитай итог». Такой код короче, его легче читать, и именно так пишут на JavaScript в реальных проектах.

Все эти методы принимают колбэк — функцию, которую вызывают для каждого элемента. Обычно это стрелочная функция из темы 8.

forEach — сделать что-то с каждым

const names = ["Аня", "Тимур", "Ира"];
names.forEach((name, index) => {
  console.log(`${index + 1}. ${name}`);
});

Вывод:

1. Аня
2. Тимур
3. Ира

Колбэк получает элемент, его номер и сам массив. forEach ничего не возвращает — это просто замена for.

map — преобразовать каждый

map создаёт новый массив той же длины из результатов колбэка:

const prices = [100, 250, 40];
const withTax = prices.map((p) => p * 1.2);
const labels = prices.map((p) => `${p} сом`);
console.log(withTax);
console.log(labels);
console.log(prices);

Вывод:

[120,300,48]
["100 сом","250 сом","40 сом"]
[100,250,40]

Исходный массив не меняется.

filter — оставить подходящие

filter возвращает новый массив только из тех элементов, для которых колбэк вернул true:

const nums = [5, 12, 8, 130, 44];
console.log(nums.filter((n) => n > 10));
console.log(nums.filter((n) => n % 2 === 0));

Вывод:

[12,130,44]
[12,8,130,44]

find и findIndex — найти первый

const users = [
  { name: "Аня", age: 15 },
  { name: "Тимур", age: 19 },
  { name: "Ира", age: 21 },
];
console.log(users.find((u) => u.age >= 18));
console.log(users.findIndex((u) => u.age >= 18));
console.log(users.find((u) => u.age > 100));

Вывод:

{"name":"Тимур","age":19}
1
undefined

(Объекты { name: …, age: … } подробно разберём в следующей теме. Пока достаточно: u.age — значение поля age.)

some и every — проверить

const ages = [15, 19, 21];
console.log(ages.some((a) => a < 18));   // true  — хотя бы один
console.log(ages.every((a) => a >= 18)); // false — все ли

reduce — свернуть в одно значение

reduce проходит по массиву и накапливает результат: сумму, максимум, строку, объект.

const cart = [300, 150, 50];
const total = cart.reduce((sum, price) => sum + price, 0);
console.log(total);

Вывод:

500

Колбэк получает «копилку» (sum) и текущий элемент, а возвращает новое значение копилки. Второй аргумент reduce (0) — начальное значение копилки. По шагам: 0 + 300 = 300 → 300 + 150 = 450 → 450 + 50 = 500.

sort — сортировка

const words = ["вишня", "арбуз", "банан"];
words.sort();
console.log(words);

const nums = [10, 9, 100, 1];
nums.sort();
console.log(nums);              // сюрприз!
nums.sort((a, b) => a - b);
console.log(nums);

Вывод:

["арбуз","банан","вишня"]
[1,10,100,9]
[1,9,10,100]

Без колбэка sort сравнивает элементы как строки, поэтому "100" оказывается раньше "9". Для чисел всегда передавай функцию сравнения: (a, b) => a - b — по возрастанию, (a, b) => b - a — по убыванию. Важно: sort (как и reverse) меняет исходный массив. Чтобы его сохранить, сортируй копию: [...arr].sort(…).

Цепочки

Методы, возвращающие массив, можно соединять в цепочку:

const orders = [120, 45, 300, 80, 15];
const bigTotal = orders
  .filter((x) => x >= 50)
  .map((x) => x * 0.9)
  .reduce((s, x) => s + x, 0);
console.log(bigTotal);

Вывод:

450

Читается как предложение: «взять заказы от 50, сделать скидку 10%, сложить».

Как это работает внутри

Внутри каждый метод — это обычный цикл. map можно было бы написать так:

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

То есть методы не быстрее циклов — они короче и понятнее. А sort с колбэком на каждом шаге спрашивает: «a и b — кто первый?». Отрицательный ответ — a раньше, положительный — b раньше, ноль — равны.

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

  1. Нет return в колбэке с фигурными скобками. arr.map((x) => { x * 2 }) даст массив undefined.
  2. forEach вместо map. forEach всегда возвращает undefined — новый массив он не создаёт.
  3. sort чисел без функции. [10, 9, 1].sort() → [1, 10, 9]. Нужно sort((a, b) => a - b).
  4. sort испортил исходный массив. Сортируй копию: [...arr].sort(…).
  5. reduce без начального значения. На пустом массиве будет ошибка. Всегда передавай второй аргумент.

Шпаргалка

Метод Что делает Возвращает
forEach(fn) вызывает fn для каждого undefined
map(fn) преобразует каждый новый массив той же длины
filter(fn) оставляет, где fn → true новый массив
find(fn) / findIndex(fn) первый подходящий элемент / номер (или undefined / -1)
some(fn) / every(fn) хотя бы один / все true / false
reduce(fn, start) сворачивает в одно итоговое значение
sort((a, b) => a - b) сортирует на месте тот же массив

Удвоить всё

Лёгкая+10 XP

Напиши функцию doubleAll(numbers), которая возвращает новый массив, где каждое число умножено на 2. Используй метод map. Исходный массив не меняется.

doubleAll([1, 2, 3])  → [2, 4, 6]

Подключи коннектор, чтобы решать задачи

Код задач выполняется на твоём компьютере — так быстрее и надёжнее, чем в браузере. Для этого нужна бесплатная программа-коннектор CodeWithMe. Подключить её нужно один раз.

Ищем коннектор на этом компьютере…

  1. 1
    Скачай коннектор для своей системы (Windows, macOS или Linux).Скачать коннекторНа странице загрузки выбери файл со своей системой в названии, например windows-amd64.
  2. 2Запусти его и выбери папку, где будут лежать твои решения. Python и Node.js он поставит туда сам, когда понадобится.
  3. 3
    Введи ниже код из 6 цифр — он написан в окне коннектора («Код для сайта CodeWithMe»). Если браузер спросит про доступ к локальной сети — разреши.

Коннектор открытый (исходный код на GitHub), работает только на твоём компьютере и выполняет код лишь после ввода кода сопряжения.