Перейти к содержимому
Теория · Методы массивов · урок 6 из 12

find, some и every

filter возвращает все подходящие элементы, а часто нужен только первый из них или ответ «есть ли такой вообще». Гонять ради этого всю ленту незачем.

Вернёмся к конвейеру. У forEach не было кнопки остановки, а у методов этого урока она есть. Работник ищет на ленте нужный ящик и, как только ответ известен, останавливает ленту. Остальные ящики он уже не смотрит.

JavaScript
const ages = [12, 17, 21, 30];

console.log(ages.find((a) => a >= 18)); // 21
console.log(ages.findIndex((a) => a >= 18)); // 2
console.log(ages.find((a) => a > 100)); // undefined
console.log(ages.findIndex((a) => a > 100)); // -1

Давайте разберём, что печатает каждая строка:

  1. find ищет первый возраст от 18 и находит 21.
  2. findIndex с тем же условием возвращает индекс этого элемента — 2.
  3. Возраста больше 100 нет, поэтому find возвращает undefined.
  4. findIndex в том же случае возвращает -1.

find и findIndex

Оба метода ищут первый элемент, подходящий под условие. Разница в том, что они возвращают.

find

find вызывает колбэк для элементов по порядку и возвращает первый элемент, для которого колбэк вернул истинное значение. Остальные элементы он уже не проверяет. Если подходящего элемента нет, find возвращает undefined.

filter с тем же условием вернул бы массив [21, 30], даже когда нужен только первый элемент.

findIndex

findIndex ищет так же, но возвращает индекс найденного элемента. Если ничего не нашлось, результат — -1, как у indexOf.

Разница с indexOf в том, что indexOf ищет равное значение, а findIndex — элемент, подходящий под условие. Индекс пригодится, когда найденный элемент нужно заменить или вырезать через splice.

some и every

Методы some и every отвечают значением boolean, то есть true или false. Метод includes тоже отвечает «есть или нет», но ищет равное значение. Условие вроде a > 20 он проверить не может.

JavaScript
console.log(ages.some((a) => a < 14)); // true
console.log(ages.every((a) => a >= 18)); // false
console.log([].some((a) => a > 0), [].every((a) => a > 0)); // false true

Обычно some и every стоят в условии if. Условие if (ages.every((a) => a >= 18)) пропускает только список, где все взрослые.

some

some возвращает true, если условие выполнено хотя бы для одного элемента. В примере есть возраст младше 14 — это 12, поэтому результат true.

every

every возвращает true, только если условие выполнено для всех элементов. В примере 12 и 17 меньше 18, поэтому результат false.

Остановка и пустой массив

some останавливается на первом true, every — на первом false. У пустого массива нет ни подходящих, ни неподходящих элементов, поэтому some даёт false, а every — true.

Ответ true у every для пустого массива удивляет многих, и на собеседовании про него любят спросить. Запомните так: every ищет элемент, который нарушает условие, а в пустом массиве таких нет.

Частая ошибка

Результат find использовали, не проверив, нашлось ли что-нибудь:

JavaScript
const names = ["Ann", "Bob"];
const found = names.find((name) => name.startsWith("Z"));

console.log(found.toUpperCase()); // ✗
TEXT
TypeError: Cannot read properties of undefined (reading 'toUpperCase')

Имени на Z в массиве нет, поэтому found равно undefined, а у undefined нет методов. Перед тем как работать с результатом, сравните его с undefined: if (found !== undefined).

Проверка if (found) здесь не годится: найденные 0 или пустая строка — ложные значения, и if решит, что ничего не нашлось. Если нужен только ответ «есть или нет», возьмите some.

Главное

  • find возвращает первый подходящий элемент или undefined, findIndex — его индекс или -1.
  • some отвечает, подходит ли хотя бы один элемент, every — подходят ли все.
  • Все четыре метода останавливаются, как только ответ известен.
  • Для пустого массива some даёт false, а every — true.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом