Работа с массивами в JS: перебор, фильтрация и трансформация

Раздел: Массивы и коллекции -> Методы массивов

Основные методы массивов в JavaScript

Как выполнить действие для каждого элемента массива?

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

const numbers = [1, 2, 3];
numbers.forEach(function(num, index) {
  console.log(`Индекс ${index}: ${num}`);
});

Js filter (метод filter в javascript)

Результат в консоли: Индекс 0: 1, Индекс 1: 2, Индекс 2: 3.

Как сделать то же самое без forEach?

Вместо forEach можно использовать цикл for...of или обычный for. Это даёт больше контроля (возможность прервать цикл).

const numbers = [1, 2, 3];
for (const num of numbers) {
  console.log(num);
}

Js foreach (метод foreach в javascript)

Цикл for...of не предоставляет индекс, но его можно получить через numbers.entries().

Типичная ошибка:

Использование await внутри forEach не работает как ожидается, так как forEach не ожидает завершения промисов. Для асинхронных операций лучше использовать for...of с await.

// Неправильно
[1,2,3].forEach(async (num) => await fetch(url));

Javascript found (метод found в javascript (возможно, find))


Как преобразовать каждый элемент массива в новый массив?

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

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

Js методы массивов (методы массивов javascript)

Как получить тот же результат без map?

Можно использовать цикл for и метод push для заполнения нового массива.

const numbers = [1, 2, 3];
const doubled = [];
for (let i = 0; i < numbers.length; i++) {
  doubled.push(numbers[i] * 2);
}

Push js (метод push для массивов в javascript)

Вариант с reduce: numbers.reduce((acc, num) => { acc.push(num*2); return acc; }, []).

Типичная ошибка:

Забыть вернуть значение из колбэка map. Если ничего не возвращать, в новом массиве будут undefined.

const result = [1,2,3].map(num => { num * 2; }); // [undefined, undefined, undefined]

Js reduce (метод reduce для массивов)

Исправление: добавить return или использовать краткую форму без фигурных скобок.


Как отфильтровать элементы по условию?

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

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]

Как отфильтровать массив без filter?

Можно использовать reduce или цикл for с проверкой.

const numbers = [1,2,3,4,5];
const evens = numbers.reduce((acc, num) => {
  if (num % 2 === 0) acc.push(num);
  return acc;
}, []);

Типичная ошибка:

Путать filter с find - первый возвращает все подходящие элементы, второй только первый. Также filter не изменяет исходный массив, но если внутри колбэка изменить элемент объекта (по ссылке), изменения отразятся в обоих массивах.


Как свернуть массив в одно значение (сумму, произведение и т.д.)?

Метод reduce последовательно обрабатывает элементы аккумулятором. Начальное значение задаётся вторым аргументом.

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 10

Если начальное значение не указано, acc станет первым элементом, а обход начнётся со второго. Это может быть опасно для пустого массива (вызовет ошибку).

Как посчитать сумму без reduce?

Обычный цикл for или forEach.

let sum = 0;
for (let i = 0; i < numbers.length; i++) {
  sum += numbers[i];
}

Типичная ошибка:

Забыть указать начальное значение 0 при суммировании чисел. Если массив пуст, без начального значения будет ошибка TypeError: reduce of empty array with no initial value.

[].reduce((a,b) => a + b); // Ошибка

Всегда указывайте начальное значение, если массив может быть пустым.


Как найти первый элемент, удовлетворяющий условию?

Метод find возвращает первый элемент, для которого колбэк вернул true, или undefined, если такого элемента нет.

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];
const user = users.find(u => u.id === 2);
console.log(user); // { id: 2, name: 'Bob' }

Как найти элемент без find?

Можно использовать filter и взять первый элемент (filter(…)[0]), но это менее эффективно, так как filter обрабатывает весь массив. Также можно использовать цикл for с прерыванием.

let found = null;
for (const u of users) {
  if (u.id === 2) { found = u; break; }
}

Типичная ошибка:

Путать find и findIndex. Первый возвращает элемент, второй - его индекс. Также нельзя забывать проверять результат на undefined.


Как отсортировать массив чисел по возрастанию?

Метод sort по умолчанию преобразует элементы в строки и сортирует лексикографически. Для чисел необходим компаратор.

const numbers = [3, 1, 10, 2];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 10]

Важно: sort мутирует исходный массив. Если нужно сохранить оригинал, предварительно сделайте копию ([...arr].sort()).

Как отсортировать без sort (для образовательных целей)?

Можно реализовать пузырьковую сортировку, но в продакшене это не рекомендуется.

for (let i = 0; i < arr.length - 1; i++) {
  for (let j = 0; j < arr.length - 1 - i; j++) {
    if (arr[j] > arr[j+1]) [arr[j], arr[j+1]] = [arr[j+1], arr[j]];
  }
}

Типичная ошибка:

Использование sort без компаратора для чисел: [1, 2, 10].sort() даст [1, 10, 2] (строковое сравнение). Также забывают, что sort изменяет массив на месте.

const arr = [1, 2, 10];
arr.sort(); // [1, 10, 2]

Дополнительные примеры и комбинирование методов

Пример
// Цепочка методов: умножить все чётные числа на 2, затем отсортировать
const numbers = [5, 2, 8, 1, 4];
const result = numbers
  .filter(num => num % 2 === 0)
  .map(num => num * 2)
  .sort((a, b) => a - b);
console.log(result); // [4, 8, 16]
Результат: [4, 8, 16]
Пример
// Группировка объектов по свойству с помощью reduce
const people = [
  { name: 'Alex', age: 25, city: 'Moscow' },
  { name: 'Bob', age: 30, city: 'London' },
  { name: 'Charlie', age: 25, city: 'Moscow' }
];
const grouped = people.reduce((acc, person) => {
  const key = person.city;
  if (!acc[key]) acc[key] = [];
  acc[key].push(person);
  return acc;
}, {});
console.log(grouped);
/* Результат:
{
  Moscow: [
    { name: 'Alex', age: 25, city: 'Moscow' },
    { name: 'Charlie', age: 25, city: 'Moscow' }
  ],
  London: [ { name: 'Bob', age: 30, city: 'London' } ]
} */
Пример
// Использование flatMap для разворачивания и трансформации
const sentences = ['Hello world', 'JavaScript is fun'];
const words = sentences.flatMap(s => s.split(' '));
console.log(words); // ['Hello', 'world', 'JavaScript', 'is', 'fun']
Пример
// Сортировка объектов по дате (строковому представлению)
const events = [
  { date: '2023-12-01', name: 'Event A' },
  { date: '2023-10-15', name: 'Event B' },
  { date: '2023-11-20', name: 'Event C' }
];
events.sort((a, b) => new Date(a.date) - new Date(b.date));
console.log(events.map(e => e.name)); // ['Event B', 'Event C', 'Event A']
Пример
// Поиск дубликатов в массиве
const arr = [1, 2, 3, 2, 4, 1];
const duplicates = arr.filter((item, index) => arr.indexOf(item) !== index);
console.log(duplicates); // [2, 1]
Пример
// Удаление элементов во время перебора (правильный способ)
const items = [1, 2, 3, 4, 5];
// Удалить все чётные числа
for (let i = items.length - 1; i >= 0; i--) {
  if (items[i] % 2 === 0) items.splice(i, 1);
}
console.log(items); // [1, 3, 5]
Результат: [1, 3, 5]
Пример
// Преобразование массива в объект с помощью reduce (key-value)
const fruits = ['apple', 'banana', 'orange'];
const fruitObject = fruits.reduce((acc, fruit, index) => {
  acc[fruit] = index;
  return acc;
}, {});
console.log(fruitObject); // { apple: 0, banana: 1, orange: 2 }

Методы массивов JavaScript - comments

En
Js методы массивов (javascript)