Как проверить, есть ли элемент в массиве JS: гайд по скорости

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как проверить, есть ли элемент в массиве JavaScript? От «просто работает» до «летает»

Вы когда-нибудь писали код и вдруг замирали, глядя на массив данных? «Есть ли здесь то, что мне нужно?» — этот вопрос мучает каждого разработчика. На Stack Overflow тема How do I check if an array includes a value in JavaScript собрала миллионы просмотров. И не зря. Казалось бы, тривиальная задача, но от её решения зависит не только читаемость кода, но и скорость работы всего приложения.

Сегодня мы разберём все способы проверки наличия элемента в массиве JavaScript. Мы не просто покажем методы — мы проведём настоящее расследование производительности. Вы узнаете, когда использовать includes(), почему indexOf() иногда быстрее, и как Set может ускорить ваш код в десятки раз. Поехали!

Классика жанра: Array.prototype.includes()

Самый современный и читаемый способ — метод includes(). Он появился в ES2016 и быстро стал стандартом де-факто. Почему? Потому что его название говорит само за себя.

const fruits = ['apple', 'banana', 'mango', 'orange'];
const hasBanana = fruits.includes('banana');
console.log(hasBanana); // true

const hasGrape = fruits.includes('grape');
console.log(hasGrape); // false

Всё просто и элегантно. includes() использует строгое сравнение (===), поэтому будьте внимательны с типами данных:

const numbers = [1, 2, 3];
console.log(numbers.includes('1')); // false — строка не равна числу

Плюсы:

  • Читаемость 10/10 — код понятен даже новичку
  • Работает с NaN (в отличие от indexOf)
  • Поддерживается всеми современными браузерами

Минусы:

  • Линейная сложность O(n) — проходит весь массив
  • Не подходит, если нужно найти индекс элемента

Ветеран: Array.prototype.indexOf()

До появления includes() все использовали indexOf(). Этот метод возвращает индекс первого найденного элемента или -1, если элемент отсутствует.

const fruits = ['apple', 'banana', 'mango'];
const index = fruits.indexOf('banana');
if (index !== -1) {
  console.log('Элемент найден на позиции', index);
} else {
  console.log('Элемент не найден');
}

Многие привыкли к такой проверке, и она по-прежнему работает. Но есть один важный нюанс: indexOf() не умеет находить NaN.

const arr = [NaN];
console.log(arr.indexOf(NaN)); // -1 — не находит!
console.log(arr.includes(NaN)); // true — находит

Это связано с тем, что NaN !== NaN в JavaScript, и indexOf использует строгое сравнение. includes() же использует алгоритм SameValueZero, который корректно обрабатывает NaN.

Когда использовать indexOf?

  • Если вам нужен индекс элемента, а не просто факт наличия
  • Если вы уверены, что в массиве нет NaN
  • В легаси-коде, где нельзя использовать ES2016+

Гибкий боец: Array.prototype.find() и findIndex()

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

const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 35 }
];

const user = users.find(u => u.age > 28);
console.log(user); // { id: 2, name: 'Bob', age: 30 }

// Проверка на существование
const exists = users.find(u => u.id === 4) !== undefined;
console.log(exists); // false

findIndex() работает аналогично, но возвращает индекс или -1.

const index = users.findIndex(u => u.name === 'Bob');
console.log(index); // 1

Плюсы:

  • Мощная фильтрация по любому условию
  • Работает с массивами объектов

Минусы:

  • Медленнее, чем includes() для простых типов
  • Избыточен, если нужно просто проверить примитив

Тяжёлая артиллерия: Set для многократных проверок

А теперь самое интересное — производительность. Что если вам нужно проверять наличие элементов тысячи раз? Например, при фильтрации большого массива или в цикле? Тут обычные методы массива начинают тормозить.

Выход — использовать Set. Эта структура данных обеспечивает поиск за O(1) в среднем, в отличие от O(n) для массивов.

// Плохо: проверка в цикле через includes
const blacklist = ['bad1', 'bad2', 'bad3', 'bad4'];
const users = ['user1', 'bad2', 'user3', 'bad4', 'user5'];

const filteredBad = users.filter(user => !blacklist.includes(user));
// Для каждого элемента users проходим по всему blacklist — O(n*m)

// Хорошо: конвертируем в Set
const blacklistSet = new Set(blacklist);
const filteredGood = users.filter(user => !blacklistSet.has(user));
// Проверка через has() — O(1) для каждого элемента — O(n)

Разница колоссальная. Давайте посмотрим на тесты производительности:

// Тест: массив из 10 000 элементов, 10 000 проверок
const bigArray = Array.from({ length: 10000 }, (_, i) => i);
const bigSet = new Set(bigArray);

console.time('Array.includes');
for (let i = 0; i < 10000; i++) {
  bigArray.includes(i);
}
console.timeEnd('Array.includes'); // ~50-100ms

console.time('Set.has');
for (let i = 0; i < 10000; i++) {
  bigSet.has(i);
}
console.timeEnd('Set.has'); // ~0.5-2ms

Set.has() быстрее в 50-100 раз! Это критично для высоконагруженных приложений, обработки данных в реальном времени или игр.

Дедовский метод: цикл for

Иногда старый добрый цикл for оказывается самым быстрым. Особенно если нужно прервать выполнение при первом совпадении.

function containsCustom(arr, value) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === value) return true;
  }
  return false;
}

const arr = [1, 2, 3, 4, 5];
console.log(containsCustom(arr, 3)); // true


                
                

Блоги

Рекомендаций по книгам