Кратко
Секция статьи "Кратко"Метод findIndex
возвращает индекс первого найденного в массиве элемента, который подходит под условие переданной функции. Если же ни одного подходящего элемента не найдётся, то метод вернёт
.
Пример
Секция статьи "Пример"Напишем код, который позволит найти человека в списке гостей мероприятия. Для этого определим функцию, которая будет получать имя из массива участников и сверять его с константой guestName
. Затем передадим эту функцию в метод findIndex
:
function isWantedGuest(element, index, array) { const guestName = 'Лиза' return element === guestName}const partyGuests = [ 'Даня', 'Саша', 'Юля', 'Лиза', 'Егор']const meetingGuests = [ 'Даня', 'Егор', 'Арсений']console.log(partyGuests.findIndex(isWantedGuest))// 3 (так как partyGuests[3] -> 'Лиза')console.log(meetingGuests.findIndex(isWantedGuest))// -1 (так как совпадений нет)
function isWantedGuest(element, index, array) { const guestName = 'Лиза' return element === guestName } const partyGuests = [ 'Даня', 'Саша', 'Юля', 'Лиза', 'Егор' ] const meetingGuests = [ 'Даня', 'Егор', 'Арсений' ] console.log(partyGuests.findIndex(isWantedGuest)) // 3 (так как partyGuests[3] -> 'Лиза') console.log(meetingGuests.findIndex(isWantedGuest)) // -1 (так как совпадений нет)
Интерактивный пример
Секция статьи "Интерактивный пример"Как пишется
Секция статьи "Как пишется"Метод findIndex
обходит массив и возвращает индекс первого элемента, который подходит под условие функции-предиката. Если ничего не подошло, то он возвращает
.
Функция, которую мы передаём в метод findIndex
, может принимать три параметра:
element
— элемент массива в текущей итерации;index
— индекс текущего элемента;array
— сам массив, который перебираем.
Определим функцию isEven
, которая проверяет, является ли число чётным, то есть делится на два без остатка. А затем найдём в массиве индекс первого такого числа через findIndex
.
// Если число чётное — вернёт true,// если нечётное — falsefunction isEven(element) { return element % 2 === 0}const onlyOddNumbers = [1, 3, 5, 7, 9]const randomNumbers = [7, 1, 6, 3, 5]console.log(onlyOddNumbers.findIndex(isEven))// -1 (элемент не найден)console.log(randomNumbers.findIndex(isEven))// 2 (так как randomNumbers[2] -> 6)
// Если число чётное — вернёт true, // если нечётное — false function isEven(element) { return element % 2 === 0 } const onlyOddNumbers = [1, 3, 5, 7, 9] const randomNumbers = [7, 1, 6, 3, 5] console.log(onlyOddNumbers.findIndex(isEven)) // -1 (элемент не найден) console.log(randomNumbers.findIndex(isEven)) // 2 (так как randomNumbers[2] -> 6)
В этом примере функция isEven
не использует параметры index
и array
, поэтому мы не стали их объявлять.
Как понять
Секция статьи "Как понять"Найти индекс первого подходящего элемента можно и с помощью цикла for
, но метод findIndex
позволяет сделать это декларативно. С помощью функции-колбэка мы описываем, какой элемент мы ищем и не описываем как должен происходить поиск. Поиск с помощью цикла for
содержал бы гораздо больше деталей.
Давайте сами попробуем реализовать findIndex
, чтобы лучше понять, как он работает «под капотом».
function findIndex(array, predicate) { for (let i = 0; i < array.length; i++) { // Если элемент удовлетворяет условию, // то возвращаем его индекс if (predicate(array[i], i, array)) { return i } } // Если ничего не подошло, // то возвращаем -1 return -1}function isEven(element) { return element % 2 === 0}const onlyOddNumbers = [1, 3, 5, 7, 9]const randomNumbers = [7, 1, 6, 3, 5]console.log(findIndex(onlyOddNumbers, isEven))// -1console.log(findIndex(randomNumbers, isEven))// 2
function findIndex(array, predicate) { for (let i = 0; i < array.length; i++) { // Если элемент удовлетворяет условию, // то возвращаем его индекс if (predicate(array[i], i, array)) { return i } } // Если ничего не подошло, // то возвращаем -1 return -1 } function isEven(element) { return element % 2 === 0 } const onlyOddNumbers = [1, 3, 5, 7, 9] const randomNumbers = [7, 1, 6, 3, 5] console.log(findIndex(onlyOddNumbers, isEven)) // -1 console.log(findIndex(randomNumbers, isEven)) // 2
Подсказки
Секция статьи "Подсказки"💡 Если используете findIndex
в условии, то всегда явно проверяйте возвращаемое значение на `-1.
На практике
Секция статьи "На практике"🛠 indexOf или findIndex
Секция статьи "🛠 indexOf или findIndex"Помимо findIndex
, у массивов есть ещё и метод indexOf
. Он работает схожим образом: возвращает индекс первого подходящего элемента или
, но, в отличии от findIndex
, принимает как аргумент не функцию-предикат, а искомое значение.
const numbers = [1, 7, 4, 6, 2, 8, 3];// Вернёт: 4// numbers[4] -> 2numbers.indexOf(2);// Вернёт: 4// numbers[4] -> 2numbers.findIndex((element) => element === 2);
const numbers = [1, 7, 4, 6, 2, 8, 3]; // Вернёт: 4 // numbers[4] -> 2 numbers.indexOf(2); // Вернёт: 4 // numbers[4] -> 2 numbers.findIndex((element) => element === 2);
Кажется, что метод indexOf
проще в использовании, и это действительно так, но из-за своей простоты, он уступает методу findIndex
в функциональности.
Например, если мы хотим осуществить поиск по массиву объектов, то indexOf
вряд ли сможет нам помочь.
const friends = [ { name: "Андрей" }, { name: "Маша" }, { name: "Артём" }];// Вернёт: -1// Элемент не найденfriends.indexOf({ name: "Артём" });// Вернёт: 2// friends[2] -> { name: "Артём" }friends.findIndex( (element) => element.name === "Артём");
const friends = [ { name: "Андрей" }, { name: "Маша" }, { name: "Артём" } ]; // Вернёт: -1 // Элемент не найден friends.indexOf({ name: "Артём" }); // Вернёт: 2 // friends[2] -> { name: "Артём" } friends.findIndex( (element) => element.name === "Артём" );
Дело в том, что переменная не хранит в себе содержимое объекта, она содержит только ссылку на него. Следовательно, indexOf
сравнивает ссылки, а не сами объекты.
// Содержит: [ссылка на объект 1]let tomato = { color: 'red' };// Содержит: [ссылка на объект 2]let strawberry = { color: 'red' };// Вернёт: false// Потому что сравниваются ссылки на разные объекты,// хотя у этих объектов и одинаковое содержаниеconsole.log(tomato === strawberry);// Вернёт: true// Потому что сравниваются одинаковые ссылки,// то есть они указывают на один и тот же объектconsole.log(tomato === tomato);
// Содержит: [ссылка на объект 1] let tomato = { color: 'red' }; // Содержит: [ссылка на объект 2] let strawberry = { color: 'red' }; // Вернёт: false // Потому что сравниваются ссылки на разные объекты, // хотя у этих объектов и одинаковое содержание console.log(tomato === strawberry); // Вернёт: true // Потому что сравниваются одинаковые ссылки, // то есть они указывают на один и тот же объект console.log(tomato === tomato);