Подтвердить что ты не робот

Array.prototype.includes против Array.prototype.indexOf

Помимо улучшенной читаемости, есть ли преимущество includes над indexOf? Они кажутся мне одинаковыми.

В чем разница между этим

var x = [1,2,3].indexOf(1) > -1; //true

И это?

var y = [1,2,3].includes(1); //true
4b9b3361

Ответ 1

tl; dr: NaN обрабатывается по-разному:

  • [NaN].indexOf(NaN) > -1 false
  • [NaN].includes(NaN) true

Из предложения :

Мотивация

При использовании массивов ECMAScript обычно требуется определить, содержит ли массив элемент. Преобладающий шаблон для этого -

if (arr.indexOf(el) !== -1) {
    ...
}

с различными другими возможностями, например. arr.indexOf(el) >= 0 или даже ~arr.indexOf(el).

Эти шаблоны имеют две проблемы:

  • Они не могут "сказать, что вы имеете в виду": вместо того, чтобы спрашивать, содержит ли массив элемент, вы спрашиваете, что такое индекс первого вхождения этого элемента в массиве, а затем сравнивать его или бить его, чтобы определить ответ на ваш реальный вопрос.
  • Они не работают NaN, так как indexOf использует строгое сравнение равенства и, следовательно, [NaN].indexOf(NaN) === -1.

Предлагаемое решение

Мы предлагаем дополнение метода Array.prototype.includes, так что приведенные выше шаблоны можно переписать как

if (arr.includes(el)) {
    ...
}

Это имеет почти ту же семантику, что и выше, за исключением того, что вместо сравнения строгого равенства используется алгоритм сравнения SameValueZero, что делает [NaN].includes(NaN) true.

Таким образом, это предложение решает обе проблемы, существующие в существующем коде.

Мы дополнительно добавляем параметр fromIndex, аналогичный Array.prototype.indexOf и String.prototype.includes, для согласованности.


Дополнительная информация:

Ответ 2

Если вас интересует производительность, на данный момент indexOf работает быстрее, но этот тест JSperf, как правило, показывает, что чем больше проходит времени, тем больше includes() будет быстрее, чем indexOf (я думаю, он будет оптимизирован и дальше).

ИМХО, я также предпочитаю писать if (arr.includes(el)) {} поскольку он более понятен и более понятен, чем if (arr.indexOf(el) !== -1) {}

Ответ 3

.indexOf() и .includes() могут использоваться для поиска элемента в массиве или для поиска символа/подстроки в данной строке.

Использование в массиве

(Ссылка на спецификацию ECMAScript)

  1. indexOf использует строгое равенство Сравнение тогда includes в includes используют SameValueZero алгоритм. По этой причине возникают следующие два отличия.

  2. Как указал Феликс Клинг, поведение отличается в случае NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Поведение также отличается в случае undefined.
let arr = [ , , ];

arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true

Использование в строке

(Ссылка на спецификацию ECMAScript)

  1. Если вы передаете RegExp в indexOf, он будет обрабатывать RegExp как строку и будет возвращать индекс строки, если он найден. Тем не менее, если вы передаете RegExp к includes в includes, он будет бросать исключение.
let str = "javascript";

str.indexOf(/\w/); // returns -1 even though the elements match the regex because /\w/ is treated as string
str.includes(/\w/); // throws TypeError: First argument to String.prototype.includes must not be a regular expression

Спектакль

Как 538ROMEO отметил, includes в indexOf includes может быть немного (очень маленький) немного медленнее (для этого нужно проверить регулярное выражение в качестве первого аргумента), чем indexOf, но в действительности, это не имеет большого значения, и ничтожно мало.

история

String.prototype.includes() был представлен в ECMAScript 2015, тогда как Array.prototype.includes() был представлен в ECMAScript 2016. Что касается поддержки браузеров, используйте их с умом.

String.prototype.indexOf() и Array.prototype.indexOf() представлены в версии ESM ECMAScript и поэтому поддерживаются всеми браузерами.

Ответ 4

Концептуально вам следует использовать indexOf, когда вы хотите использовать positionOffode, просто дайте вам извлечь значение или работать с массивом, то есть с помощью среза, сдвига или сплита после того, как вы получите позицию элемента. С другой стороны, Use Array.includes только для того, чтобы знать, находится ли значение внутри массива, а не позиция, потому что вам это неинтересно.