Частая задача - понять, есть ли значение в массиве. Для этого часто используют includes и indexOf.
includesотвечает на вопрос “есть ли элемент” и возвращает booleanindexOfищет индекс элемента и возвращает число (или-1, если не найден)
Оба метода не меняют исходный массив.
includes: есть ли элемент
includes возвращает true или false.
const colors = ["red", "green", "blue"];
console.log(colors.includes("green")); // true
console.log(colors.includes("black")); // false
Поиск с позиции
Второй аргумент - индекс, с которого начинать поиск.
const items = ["a", "b", "a", "c"];
console.log(items.includes("a")); // true
console.log(items.includes("a", 1)); // true (найдет "a" на индексе 2)
console.log(items.includes("a", 3)); // false
indexOf: индекс или -1
indexOf возвращает индекс первого совпадения или -1, если совпадения нет.
const colors = ["red", "green", "blue"];
console.log(colors.indexOf("green")); // 1
console.log(colors.indexOf("black")); // -1
Поиск с позиции
const items = ["a", "b", "a", "c"];
console.log(items.indexOf("a")); // 0
console.log(items.indexOf("a", 1)); // 2
Как проверить наличие через indexOf
Обычно сравнивают с -1:
const items = ["a", "b", "c"];
const hasB = items.indexOf("b") !== -1;
console.log(hasB); // true
Что выбрать: includes или indexOf
Практичное правило:
- если нужен только ответ “есть или нет” -
includesчитается лучше - если нужен индекс -
indexOf(или другие методы, напримерfindIndex)
Важный нюанс: NaN
indexOf не умеет находить NaN, потому что NaN !== NaN. includes умеет.
const nums = [1, NaN, 3];
console.log(nums.includes(NaN)); // true
console.log(nums.indexOf(NaN)); // -1
Поэтому для проверки наличия NaN лучше includes.
Нюансы сравнения
Оба метода ищут строгое совпадение по значению (для объектов - по ссылке).
const a = { id: 1 };
const b = { id: 1 };
const items = [a];
console.log(items.includes(a)); // true
console.log(items.includes(b)); // false
Объекты разные, хотя выглядят одинаково.
Частые ошибки
1) Проверка indexOf без сравнения с -1
0 - это валидный индекс, но в условиях он falsy. Поэтому так писать нельзя:
const items = ["a", "b"];
if (items.indexOf("a")) {
console.log("found");
} else {
console.log("not found");
}
indexOf("a") вернет 0, и условие пойдет в ветку “not found”.
Правильно:
const items = ["a", "b"];
if (items.indexOf("a") !== -1) {
console.log("found");
} else {
console.log("not found");
}
Или проще через includes:
const items = ["a", "b"];
if (items.includes("a")) {
console.log("found");
}
2) Ожидание, что includes/indexOf ищут по “содержимому” объектов
Они сравнивают ссылки, поэтому для объектов обычно используют find с условием:
const users = [{ id: 1 }, { id: 2 }];
const found = users.find(u => u.id === 2);
console.log(found); // { id: 2 }
Что стоит запомнить
includes(value)возвращает true/false.indexOf(value)возвращает индекс или -1.- Для “есть ли” обычно удобнее
includes, для индекса -indexOf. includesумеет находитьNaN,indexOf- нет.- Для объектов поиск идет по ссылке, а не по содержимому.