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

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

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

Зачем нужны методы массивов

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

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

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

Методы массивов — набор готовых функций для работы с массивами. Они уже встроены в JavaScript (именно в сами массивы), их не нужно писать самому. 

Сегодня разберем первую пятерку самых полезных из них: includes, indexOf, splice, forEach и find. а во второй части — тройку других. Поехали.

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

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

Начать изучение →

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. Мы найдем индекс задачи и сразу сделаем splice, оставив части массива до и после нее:

// Наш список дел
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++) {
   f    n(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);
Результат в консоли.
Результат в консоли.

Да, здесь тоже используется callback-функция, вызываемая при обходе массива циклом. Если функция вернет true, то элемент удовлетворяет критериям поиска и find его же и вернет. То есть настраивать условие поиска может сам разработчик.

Кстати, find в отличие от indexOf возвращает сам элемент, а не его порядковый номер.

Что принимает: callback-функцию, принимающую три аргумента и возвращающую значение типа boolean.

Аргументы:

  • element — текущий элемент массива;

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

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

Что возвращает: найденный элемент или undefined, если ничего не найдено.

Если поиск становится сложным и indexOf недостаточно, то find точно поможет. Он возвращает сам элемент, а не его индекс.

Итог

Сегодня мы разобрали пять ключевых методов массивов, избавляющих нас от лишних хлопот:

  • includes — проверяет наличие элемента;

  • indexOf — находит индекс элемента;

  • splice — изменяет массив;

  • forEach — перебирает элементы;

  • find — ищет по условию.

Не переживайте, если с первого раза не все запомнили. Главное — понять концепцию, что для каждой задачи по работе со списками в JavaScript, скорее всего, уже есть готовый и удобный метод. Начинайте с forEach и includes, а потом уже переходите к find и splice.

В следующей части мы познакомимся с еще более крутыми методами, которые не просто перебирают массив, а превращают его во что-то новое: map, filter и sort.

Комментарии (0)