Learn JavaScript

includes и indexOf: проверка наличия в массиве

Частая задача - понять, есть ли значение в массиве. Для этого часто используют includes и indexOf.

  • includes отвечает на вопрос “есть ли элемент” и возвращает boolean
  • indexOf ищет индекс элемента и возвращает число (или -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 - нет.
  • Для объектов поиск идет по ссылке, а не по содержимому.