find, some и every
filter возвращает все подходящие элементы, а часто нужен только первый из них или ответ «есть ли такой вообще». Гонять ради этого всю ленту незачем.
Вернёмся к конвейеру. У forEach не было кнопки остановки, а у методов этого урока она есть. Работник ищет на ленте нужный ящик и, как только ответ известен, останавливает ленту. Остальные ящики он уже не смотрит.
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Давайте разберём, что печатает каждая строка:
findищет первый возраст от18и находит21.findIndexс тем же условием возвращает индекс этого элемента —2.- Возраста больше
100нет, поэтомуfindвозвращаетundefined. 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 он проверить не может.
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 использовали, не проверив, нашлось ли что-нибудь:
const names = ["Ann", "Bob"];
const found = names.find((name) => name.startsWith("Z"));
console.log(found.toUpperCase()); // ✗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 и подпишись на канал — откроются все уроки.