Начиная с ECMAScript 2016 в JavaScript появился новый метод includes для работы с массивами. По своей сути он очень сильно напоминает indexOf. В этой статье я хочу рассмотреть подробнее для чего был введен этод метод и в чем его отличие от indexOf.
Итак, метод Array.prototype.includes определяет содержится ли в массиве искомое значение и возвращает true или false. Таким образом, в отличие от indexOf, который возвращает целое число, includes возвращает значение типа boolean. Это нововведение поможет разработчикам писать более чистый и понятный код.
Например, вот стандартный пример проверки того, содержится ли элемент в массиве, с помощью indexOf:
Используя includes, то же самое можно написать так:
Также при внедрении этого метода были учтены некоторые неочевидные особенности, замеченные при работе с indexOf. В отношении значений NaN поведение этого метода отличается.
Рассмотрим на примере:
Таким образом, indexOf(NaN) всегда возвращает -1, независимо от того содержится ли это значение в массиве, а includes(NaN) возвращает true или false в зависимости от того есть этот элемен в массиве или нет.
Оценка производительности javascript методов не такая уж очевидная вешь, так как по сути в разных браузерах одна и та же функция может быть реализована по-разному в зависимости от языка, на котором написан сам браузер. К тому же очень много зависит от компьютера, на котором делается эта оценка. Но, тем не менее, я попытался сделать небольшой анализ.
Я создал массив из 10000 целых положительных чисел и использовал для анализа сайт jsbench.github.io. В обоих случаях, для чистоты эксперимента, был использован один и тот же массив. Оценка производилась в браузерах Chrome 53 и Firefox 48.
Получается, что в Chrome indexOf всегда работает быстрее, а в Firefox ощутимой разницы практически нет (кроме случая, когда в массиве нет искомого элемента). И поведение нового метода в Firefox кажется более логичным, так как в общем-то indexOf и includes по логике должны иметь одну и ту же вычислительную сложность.
Аналогичный метод был добавлен и для работы со строками начиная с ECMAScript 2015. Ранее в Firefox в версиях с 18 по 39 этот метод существовал под именем contains, однако из-за проблем совместимости он был переименован в includes().
В заключение следует отметить, что данный метод поддерживается пока что не всеми браузерами.
Массивы
Итак, метод Array.prototype.includes определяет содержится ли в массиве искомое значение и возвращает true или false. Таким образом, в отличие от indexOf, который возвращает целое число, includes возвращает значение типа boolean. Это нововведение поможет разработчикам писать более чистый и понятный код.
Например, вот стандартный пример проверки того, содержится ли элемент в массиве, с помощью indexOf:
var numbers = [3, 5, 8, 11, 23, 7];
if (numbers.indexOf(1) !== -1) {
// ...
}
Используя includes, то же самое можно написать так:
var numbers = [3, 5, 8, 11, 23, 7];
if (numbers.includes(1)) {
// ...
}
Также при внедрении этого метода были учтены некоторые неочевидные особенности, замеченные при работе с indexOf. В отношении значений NaN поведение этого метода отличается.
Рассмотрим на примере:
var numbers = [3, 5, 8, 11, 23, 7, NaN];
if (numbers.indexOf(NaN) !== -1) {
// Этот код не выполнится
}
if (numbers.includes(NaN)) {
// Этот код выполнится
}
Таким образом, indexOf(NaN) всегда возвращает -1, независимо от того содержится ли это значение в массиве, а includes(NaN) возвращает true или false в зависимости от того есть этот элемен в массиве или нет.
Производительность
Оценка производительности javascript методов не такая уж очевидная вешь, так как по сути в разных браузерах одна и та же функция может быть реализована по-разному в зависимости от языка, на котором написан сам браузер. К тому же очень много зависит от компьютера, на котором делается эта оценка. Но, тем не менее, я попытался сделать небольшой анализ.
Я создал массив из 10000 целых положительных чисел и использовал для анализа сайт jsbench.github.io. В обоих случаях, для чистоты эксперимента, был использован один и тот же массив. Оценка производилась в браузерах Chrome 53 и Firefox 48.
Chrome | ||
---|---|---|
includes | indexOf | |
элемент есть в середине массива |
8,361 ops/sec ±0.38% | 31,296 ops/sec ±0.65% |
элемент есть в начале массива |
22,043,904 ops/sec ±1.89% | 136,512,737 ops/sec ±2.06% |
искомого эелемента нет в массиве |
4,018 ops/sec ±0.71% | 95,221 ops/sec ±0.53% |
Firefox | ||
---|---|---|
includes | indexOf | |
элемент есть в середине массива |
84,880 ops/sec ±0.59% | 86,612 ops/sec ±1.35% |
элемент есть в начале массива |
34,087,623 ops/sec ±0.99% | 33,196,839 ops/sec ±0.84% |
искомого эелемента нет в массиве |
25,253 ops/sec ±2.75% | 14,994 ops/sec ±1.16% |
Получается, что в Chrome indexOf всегда работает быстрее, а в Firefox ощутимой разницы практически нет (кроме случая, когда в массиве нет искомого элемента). И поведение нового метода в Firefox кажется более логичным, так как в общем-то indexOf и includes по логике должны иметь одну и ту же вычислительную сложность.
Строки
Аналогичный метод был добавлен и для работы со строками начиная с ECMAScript 2015. Ранее в Firefox в версиях с 18 по 39 этот метод существовал под именем contains, однако из-за проблем совместимости он был переименован в includes().
В заключение следует отметить, что данный метод поддерживается пока что не всеми браузерами.
Браузер | Массив | Строки |
---|---|---|
Chrome | 47 | 41 |
Firefox | 43 | 40 |
IE | нет | нет |
Opera | 34 | нет |
Safari | 9 | 9 |