А ведь правда, если посмотреть на любой сайт, то можно заметить, что многие элементы состоят из списков и наборов: лента новостей в соцсетях, товары в интернет-магазине, сообщения в чате. Для хранения этих данных нужны массивы, и важно не бояться работы с ними.
Ранее я уже рассказывал о том, что такое массивы. Если вы только начинаете изучать JavaScript, то настоятельно рекомендую прочитать эту статью.
Зачем нужны методы массивов?
Итак, вы уже знаете, что такое массивы — это упорядоченные наборы данных, как обычные нумерованный списки. Вы умеете их создавать, добавлять элементы и обрабатывать с помощью циклов.
Но представьте себе такую ситуацию: есть список заказов в интернет-магазине, и вам нужно найти конкретный заказ по номеру. Или вы получили от сервера список товаров, но нужно оставить только те, что есть в наличии.
Решать такие задачи можно через обычный цикл, например, `for`. Но это долго, неудобно и можно легко сделать ошибку в логике кода. Учитывая, что эта задача довольно типичная и решать ее приходится часто, JavaScript позаботился о вас и кое-что приготовил.
Методы массивов — набор готовых функций для работы с массивами. Они уже встроены в JavaScript (именно в сами массивы), их не нужно писать самому.
Сегодня разберем первую пятерку самых полезных из них: includes, indexOf, splice, forEach и find. а во второй части — тройку других. Поехали.
includes — для проверки наличия элемента
Представим ситуацию: вы заходите на сайт и видите кнопку «Добавить в избранное». Но если товар уже в избранном, кнопка должна выглядеть по-другому. Например, быть заполненной сердечком. Как быстро проверить, есть ли текущий товар в списке избранного?
includes — проверяет, есть ли искомый элемент в массиве, и возвращает true (если нашел) или false (если нет).
Смотрим пример использования:
// Массив ID товаров
const favoriteProductIds = [123, 456, 789, 234];
// ID текущего товар, который просматривает пользователь
const currentProductId = 456;
// Проверяем, есть ли этот товар в избранном
const isFavorite = favoriteProductIds.includes(currentProductId);
if (isFavorite) {
console.log('Показываем заполненное сердечко ❤️');
} else {
console.log('Показываем пустое сердечко 🤍');
}

В итоге мы получаем нужный результат. Метод ищет в массиве точное совпадение с переданным значением. Он достаточно простой, но давайте рассмотрим его чуть подробнее.
Принимает: один обязательный параметр — значение, которое ищем.
Возвращает: булево значение (true или false).
Используйте includes, когда вам нужен простой ответ на вопрос «Есть ли этот элемент в массиве?».
indexOf — если нужно знать, где элемент
Знание о положении элемента в массиве, то есть индекса элемента помогает решать ряд задач. Ну, скажем, вы хотите проверить находится ли имя студента в конце списка при условии, что это имя вообще там есть.
Да, includes определяет наличие элемента в массиве, но он не отдает его положение.
Решаем с помощью indexOf. indexOf — отдает индекс (номер) первого найденного элемента. Если элемент не найден, вернется -1.
// Список студентов
const students = ['Саша', 'Оля', 'Оля', 'Даша', 'Паша'];
// Мы хотим узнать, каким по счету стоит 'Паша'
const pashaIndex = students.indexOf('Паша');
if (pashaIndex === students.length - 1) {
console.log(`Паша в конце списка (${pashaIndex})`);
}

Важно то, что indexOf возвращает индекс первого найденного элемента, если добавить еще одного Пашу в середину списка, то в консоли вы ничего не увидите, так как условие проверки не выполнится.
Кстати, в случае если в списке нет искомого элемента, то indexOf вернет -1. Так метод избавлять вас от дополнительных проверок в случае альтернативных кейсов:
// Список студентов
const students = ['Саша', 'Оля', 'Оля', 'Даша', 'Паша'];
// А если попробовать найти несуществующего студента?
const annaIndex = students.indexOf('Аня');
if (annaIndex === -1) {
console.log('Этого имени нет в списке!');
}

Еще раз, indexOf выполняет поиск нужного элемента в массиве. Он простой, но все же предлагаю посмотреть на «инструкцию» использования.
Что принимает: один обязательный параметр — значение, которое ищем.
Что возвращает: число (индекс элемента) или -1, если элемент не найден.
Используете его в случаях, когда вам нужно не просто определить наличие элемента, но еще и узнать о его позиции в массиве.
splice — не только удаляет, но и добавляет куда надо
Предположим, что вы создаете небольшое приложения для ведения списка дел — классическая задача. Список дел — это массив строк. Добавлять в начало и конец списка вы уже умеете (смотрите статью про массивы). Удалять — тоже. Но что, если элемент или несколько элементов нужно вставить в нужную позицию, например, середину списка?
splice — это самый мощный и гибкий метод для изменения исходного массива. Он может удалять, добавлять и заменять элементы в любом месте.
Смотрим, как вставить несколько элементов в середину массива с помощью splice на примере:
// Наш список дел
const todoList = ['Поесть', 'Попить кофе', 'Написать статью', 'Поспать'];
// Вставляем элементы
todoList.splice(2, 0, 'Покормить кота', 'Зарядить телефон', 'Погулять');
console.log(todoList);

Готово, новые задачи вставлены в нужное место и splice отлично с этим справляется. Но этот метод имеет уже больше параметров, давайте посмотрим:todoList.splice(startIndex, deleteCount, elem1, ..., elemN)
Что принимает
- startIndex — индекс начала изменения массива. Если startIndex отрицателен, то отсчет начинается с конца.
- deleteCount — сколько элементов удалить. Если указать 0, то просто добавляются новые в указанное место. Но если в deleteCount вовсе не передать значение, то удалятся все элементы после startIndex.
- …items — элементы, которые нужно добавить (необязательно).
Что возвращает: массив из удаленных элементов.
Обратите внимание, это важно. Метод splice является «мутирующим», он изменяет исходный массив вместо создания нового. Если вам нужно сохранить данные в первоначальном виде, то возможно, стоит подумать о создании копии массива перед применением splice.
Я показал, как вставить элементы в массив, а теперь покажу, как удалить. Но в комбинации с indexOf. Мы найдем индекс задачи и сразу ее удалим:
// Наш список дел
const todoList = ["Поесть", "Попить кофе", "Написать статью", "Поспать"];
const taskIndex = todoList.indexOf("Поспать");
if (taskIndex !== -1) {
// Удаляем элемент
todoList.splice(taskIndex, 1);
}
console.log(todoList);

И все работает, элемент удален. Обратите внимание, я делаю проверку наличия элемента в массиве и это не случайно! Для эксперимента удалите if из кода в indexOf, подставьте «Поесть» и посмотрите на результат. Почему он таким получается?
А мы идем дальше.
forEach — это удобнее, чем классический for
Несомненно, практически любые задачи по обработке массива можно решить с помощью цикла for. Но, как мы уже знаем, большинство задач однотипны, и для их решения есть методы.
forEach — это красивый и читаемый способ заменить цикл for для простого перебора всех элементов массива.
Например, у вас есть список email-ов всех пользователей, который нужно просто вывести в консоль. Я предлагаю решить эту задачу с помощью обычного цикла for.
// Массив пользователей
const users = ['sasha@mail.com', 'masha@mail.com', 'pasha@mail.com'];
for (let i = 0; i < users.length; i++) {
console.log(`${i + 1}: ${users[i]}`);
}

Все отлично работает, и результат выводится в консоль. Обратите внимание на то, как выглядит описание цикла. Мне пришлось создать счетчик, проверять значение в i и при это постоянно увеличивать на единицу. А ведь задача с обходом массива встречается очень часто.
Сейчас я предлагаю создать свою собственную функцию myForEach для обхода массива, которая избавить нас от цикла for и его полного описания. «Но ведь forEach уже есть»: скажете вы. Да, есть, но так как в этом методе используется callback-функция, для ясности будет удобнее начать с написания своей функции.
Начнем:
// Массив пользователей
const users = ["sasha@mail.com", "masha@mail.com", "pasha@mail.com"];
function myForEach(array, fn) {
for (let i = 0; i < array.length; i++) {
fn(array[i], i, array);
}
}
myForEach(users, function (user, index) {
console.log(`${index + 1}: ${user}`);
});

Обратите внимание, функция myForEach принимает два аргумента: массив и callback-функцию, вызывающуюся для каждого элемента массива. В свою очередь callback-функция принимает три аргумента, которые можно использовать опционально: элемент, индекс и сам массив (может быть полезным в некоторых задачах). Не запутались еще?
В итоге myForEach, как бы скрывает от нас реализацию цикла, оставляя своему пользователю, то есть нам, самые интересные задачи. В общем, myForEach можно использовать много раз не думая о создании цикла. Удобно же!
И теперь предлагаю применить метод, который есть в JS. Все практически так же как в нашей функции. Только название массива выносится перед forEach:
// Массив пользователей
const users = ["sasha@mail.com", "masha@mail.com", "pasha@mail.com"];
users.forEach(function (user, index) {
console.log(`${index + 1}: ${user}`);
});

И так, forEach выполняет переданную функцию один раз для каждого элемента массива. Давайте еще раз посмотрим на то, как он устроен:
forEach принимает callback-функцию. Дальше эта функция, автоматически получает три аргумента (часто используют только первый): element — текущий элемент массива; index — его индекс (необязательно); array — сам массив (необязательно).
forEach — это ваш цикл на каждый день. Используйте его, когда нужно просто что-то сделать с каждым элементом, не создавая новый массив.
find— когда indexOf не достаточно
Метод indexOf отлично справляется с ситуациями, которые не требуют глубокой и детальной проверки элементов массива, как в случае с поиском по массиву объектом. Пожалуй, с этой задачей indexOf не справится, в отличие от find.
find — метод для поиска первого элемента в массиве, который удовлетворяет заданному условию.
Сразу смотрим пример использования:
// Товары
const products = [
{ title: 'Футболка', inStock: false },
{ title: 'Джинсы', inStock: false },
{ title: 'Пальто', inStock: true },
];
// Найдем первый товар, который есть в наличии
const foundProduct = products.find(function (product) {
// Функция должна вернуть true для подходящего элемента
return product.inStock === true;
});
console.log(foundProduct);

Да, здесь, как и в forEach тоже используется callback-функция вызываемая при обходе массива циклом. Если функция вернет true, то элемент удовлетворяет критериям поиска и find его же и вернет. То есть настраивать условие поиска может сам разработчик.
Кстати, find в отличие от indexOf возвращает сам элемент, а не его порядковый номер.
Что принимает: callback-функцию, принимающую аргументы.
Аргументы:
- element — текущий элемент массива;
- index — его индекс (необязательно);
- array — сам массив (необязательно).
Еще эта callback-функция возвращает значение типа boolean.
Что возвращает: Найденный элемент или undefined, если ничего не найдено.
Если поиск становится сложным и indexOf не достаточно, то find точно поможет. Он возвращает сам элемент, а не индекс.
Итог
Сегодня мы разобрали 5 ключевых методов массивов, избавляющих нас от лишних хлопот:
- includes — проверяет наличие элемента;
- indexOf — находит индекс элемента;
- splice — изменяет массив;
- forEach — перебирает элементы;
- find — ищет по условию.
Не переживайте, если с первого раза не все запомнили. Главное, понять концепцию, для каждой задачи по работе со списками в JavaScript, скорее всего, уже есть готовый и удобный метод. Начинайте с forEach и includes, они самые простые, а потом уже переходите к find и splice.
В следующей части мы познакомимся с еще более крутыми методами, которые не просто перебирают массив, а превращают его во что-то новое: map, filter и sort.