FindIndex: примеры (JAVASCRIPT)

Использование findIndex в JavaScript: полный обзор
Раздел: Массивы, Поиск
findIndex(callback: function, thisArg?: any): number

Основы метода findIndex

Array.prototype.findIndex()

– это метод JavaScript для поиска индекса первого элемента в массиве, который удовлетворяет заданному условию, реализованному в функции-колбэке. Если элемент не найден, метод возвращает -1. Он не изменяет исходный массив.

Метод применяется, когда требуется найти позицию элемента по сложному критерию, а не просто по значению (для чего подходит indexOf()).

Синтаксис: arr.findIndex(callback(element[, index[, array]])[, thisArg]).

  • callback – функция, выполняющаяся для каждого элемента. Должна возвращать true для элемента, который прошёл проверку.
  • element – текущий обрабатываемый элемент.
  • index (необязательный) – индекс текущего элемента.
  • array (необязательный) – массив, по которому осуществляется проход.
  • thisArg (необязательный) – значение, используемое в качестве this при выполнении колбэка.

Возвращаемое значение: индекс первого элемента, прошедшего проверку, или -1, если такой элемент не найден.

Простые примеры использования

Пример 1: Поиск индекса числа больше 10.

const numbers = [5, 12, 8, 130, 44];
const result = numbers.findIndex(num => num > 10);
console.log(result);
// 1 (первый элемент, удовлетворяющий условию, это 12 с индексом 1)

Пример 2: Поиск индекса объекта по свойству.

const fruits = [
  {name: 'яблоки', quantity: 2},
  {name: 'бананы', quantity: 0},
  {name: 'вишни', quantity: 5}
];
const result = fruits.findIndex(fruit => fruit.name === 'вишни');
console.log(result);
// 2

Пример 3: Использование всех параметров колбэка и thisArg.

function isPrime(element, index, array) {
  let start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) return false;
  }
  return element > 1;
}
const numbers = [4, 6, 8, 9, 11];
const result = numbers.findIndex(isPrime);
console.log(result);
// 4 (число 11 простое, его индекс 4)

Пример 4: Элемент не найден.

const result = [1, 2, 3].findIndex(num => num > 5);
console.log(result);
// -1

Похожие методы в JavaScript

  • indexOf() / lastIndexOf(): Ищут индекс элемента по строгому равенству (===). Не принимают функцию для сложных условий. Предпочтительны для поиска примитивных значений.
  • find(): Аналогичен findIndex(), но возвращает сам найденный элемент или undefined. Выбирают в зависимости от того, нужен элемент или его позиция.
  • some(): Проверяет, удовлетворяет ли хотя бы один элемент условию. Возвращает true/false. Используют, когда важен факт наличия, а не индекс.
  • Array.filter() + indexOf(): Комбинация для поиска всех индексов элементов, удовлетворяющих условию. Требует больше ресурсов.

Типичные ошибки

1. Колбэк не возвращает булево значение.

// Колбэк ничего не возвращает (возвращает undefined)
const arr = [1, 2, 3];
const index = arr.findIndex(item => { item > 1; }); // Нет return
console.log(index);
// -1 (для всех элементов возвращается undefined, что интерпретируется как false)

2. Попытка использования для поиска NaN.

console.log([NaN].indexOf(NaN)); // -1 (не находит)
console.log([NaN].findIndex(x => Number.isNaN(x))); // 0 (корректно)
// indexOf не может найти NaN, findIndex решает эту проблему

3. Мутация массива внутри колбэка может привести к непредсказуемому поведению.

const arr = [1, 2, 3, 4];
const index = arr.findIndex((num, i, array) => {
  array.pop(); // Изменяем массив в процессе итерации
  return num > 2;
});
console.log(index, arr);
// Результат может различаться в зависимости от движка JS

4. Поиск в разреженном массиве.

const sparseArray = [1, , , 4];
const index = sparseArray.findIndex(x => x === undefined);
console.log(index);
// 1 (пропущенные элементы обрабатываются как undefined)

История изменений

Метод findIndex() был добавлен в спецификацию ECMAScript 2015 (ES6). С тех пор его поведение остается стабильным.

Важные аспекты реализации: метод является универсальным и может быть вызван для любого массивоподобного объекта, у которого есть свойство length и индексированные свойства (например, NodeList, arguments).

Поддержка в браузерах: полная поддержка во всех современных браузерах, включая Internet Explorer (не поддерживается). Для старых сред может потребоваться полифил.

Расширенные примеры

Пример 1: Поиск с использованием контекста (thisArg).

Пример javascript
class Searcher {
  constructor(target) {
    this.target = target;
  }
  check(value) {
    return value === this.target;
  }
}
const array = ['a', 'b', 'c'];
const searcher = new Searcher('b');
const index = array.findIndex(function(item) {
  return this.check(item);
}, searcher);
console.log(index); // 1
// 1

Пример 2: Поиск индекса в массиве объектов с несколькими условиями.

Пример javascript
const users = [
  {id: 1, name: 'Анна', active: true},
  {id: 2, name: 'Борис', active: false},
  {id: 3, name: 'Анна', active: true}
];
const index = users.findIndex(u => u.name === 'Анна' && u.active);
console.log(index); // 0 (первая активная Анна)
// 0

Пример 3: Поиск индекса в части массива (имитация параметра fromIndex).

Пример javascript
function findIndexFrom(array, predicate, fromIndex = 0) {
  const subArray = array.slice(fromIndex);
  const foundIndex = subArray.findIndex(predicate);
  return foundIndex === -1 ? -1 : foundIndex + fromIndex;
}
const arr = [1, 2, 3, 2, 1];
const idx = findIndexFrom(arr, x => x === 2, 2);
console.log(idx); // 3 (второе вхождение двойки)
// 3

Пример 4: Поиск индекса в массиве с использованием сторонней библиотеки (например, Lodash) не требуется, но для сложных условий можно использовать findIndex с сложным колбэком.

Пример javascript
const data = [
  {values: [1, 2]},
  {values: [3, 4, 5]},
  {values: [6]}
];
const index = data.findIndex(obj => obj.values.includes(4));
console.log(index); // 1
// 1

Пример 5: Обработка edge-case с пустым массивом и массивом из одного элемента.

Пример javascript
console.log([].findIndex(x => true)); // -1
console.log([undefined].findIndex(x => x === undefined)); // 0
console.log([null].findIndex(x => x == null)); // 0
// -1
// 0
// 0

Аналоги в других языках программирования

Python: Используют метод index() в списках с генератором или циклом. Прямого аналога нет, но можно использовать next() с enumerate().

# Пример поиска индекса первого четного числа
numbers = [1, 3, 5, 8, 9]
try:
    index = next(i for i, num in enumerate(numbers) if num % 2 == 0)
    print(index)
except StopIteration:
    print(-1)
# 3

PHP: Функция array_search() с флагом strict или array_filter() с key().

// Поиск индекса по значению с array_search()
$array = ['a' => 5, 'b' => 12, 'c' => 8];
$key = array_search(12, $array); // 'b'
// Для сложных условий используют array_filter()
$filtered = array_filter($array, function($val) { return $val > 10; });
$keys = array_keys($filtered); // ['b']
// Возвращает ключ 'b', а не числовой индекс

C# (LINQ): Метод FindIndex() у List очень похож на JavaScript.

List numbers = new List {5, 12, 8, 130, 44};
int index = numbers.FindIndex(num => num > 10); // 1

SQL: Нет прямого аналога, но для поиска позиции в результате запроса можно использовать ROW_NUMBER().

JS findIndex function comments

En
FindIndex Returns the index of the first element in the array that satisfies the provided testing function.