Перебор: forEach
Метод arr.forEach позволяет запускать функцию для каждого элемента массива.
Его синтаксис:
arr.forEach(function(item, index, array) {
// ... делать что-то с item
});
Например, этот код выведет на экран каждый элемент массива:
// Вызов alert для каждого элемента
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
А этот вдобавок расскажет и о своей позиции в массиве:
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} имеет позицию ${index} в ${array}`);
});
Результат функции (если она вообще что-то возвращает) отбрасывается и игнорируется.
Поиск в массиве
Далее рассмотрим методы, которые помогут найти что-нибудь в массиве.
indexOf/lastIndexOf и includes
Методы arr.indexOf, arr.lastIndexOf и arr.includes имеют одинаковый синтаксис и делают по сути то же самое, что и их строковые аналоги, но работают с элементами вместо символов:
arr.indexOf(item, from)
ищетitem
, начиная с индексаfrom
, и возвращает индекс, на котором был найден искомый элемент, в противном случае-1
.arr.lastIndexOf(item, from)
– то же самое, но ищет справа налево.arr.includes(item, from)
– ищетitem
, начиная с индексаfrom
, и возвращаетtrue
, если поиск успешен.
Например:
let arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1
alert( arr.indexOf(false) ); // 2
alert( arr.indexOf(null) ); // -1
alert( arr.includes(1) ); // true
Обратите внимание, что методы используют строгое сравнение ===
. Таким образом, если мы ищем false
, он находит именно false
, а не ноль.
Если мы хотим проверить наличие элемента, и нет необходимости знать его точный индекс, тогда предпочтительным является arr.includes
.
Кроме того, очень незначительным отличием includes
является то, что он правильно обрабатывает NaN
в отличие от indexOf/lastIndexOf
:
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (должен быть 0, но === проверка на равенство не работает для NaN)
alert( arr.includes(NaN) );// true (верно)
find и findIndex
Представьте, что у нас есть массив объектов. Как нам найти объект с определённым условием?
Здесь пригодится метод arr.find.
Его синтаксис таков:
let result = arr.find(function(item, index, array) {
// если true - возвращается текущий элемент и перебор прерывается
// если все итерации оказались ложными, возвращается undefined
});
Функция вызывается по очереди для каждого элемента массива:
item
– очередной элемент.index
– его индекс.array
– сам массив.
Если функция возвращает true
, поиск прерывается и возвращается item
. Если ничего не найдено, возвращается undefined
.
Например, у нас есть массив пользователей, каждый из которых имеет поля id
и name
. Попробуем найти того, кто с id == 1
:
let users = [
{id: 1, name: "Вася"},
{id: 2, name: "Петя"},
{id: 3, name: "Маша"}
];
let user = users.find(item => item.id == 1);
alert(user.name); // Вася
В реальной жизни массивы объектов – обычное дело, поэтому метод find
крайне полезен.
Обратите внимание, что в данном примере мы передаём find
функцию item => item.id == 1
, с одним аргументом. Это типично, дополнительные аргументы этой функции используются редко.
Метод arr.findIndex – по сути, то же самое, но возвращает индекс, на котором был найден элемент, а не сам элемент, и -1
, если ничего не найдено.
filter
Метод find
ищет один (первый попавшийся) элемент, на котором функция-колбэк вернёт true
.
На тот случай, если найденных элементов может быть много, предусмотрен метод arr.filter(fn).
Синтаксис этого метода схож с find
, но filter
возвращает массив из всех подходящих элементов:
let results = arr.filter(function(item, index, array) {
// если true - элемент добавляется к результату, и перебор продолжается
// возвращается пустой массив в случае, если ничего не найдено
});
Например:
let users = [
{id: 1, name: "Вася"},
{id: 2, name: "Петя"},
{id: 3, name: "Маша"}
];
// возвращает массив, состоящий из двух первых пользователей
let someUsers = users.filter(item => item.id < 3);
alert(someUsers.length); // 2