Помимо улучшенной читаемости, есть ли преимущество includes
над indexOf
? Они кажутся мне одинаковыми.
В чем разница между этим
var x = [1,2,3].indexOf(1) > -1; //true
И это?
var y = [1,2,3].includes(1); //true
Помимо улучшенной читаемости, есть ли преимущество includes
над indexOf
? Они кажутся мне одинаковыми.
В чем разница между этим
var x = [1,2,3].indexOf(1) > -1; //true
И это?
var y = [1,2,3].includes(1); //true
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
, для согласованности.
Дополнительная информация:
Если вас интересует производительность, на данный момент indexOf работает быстрее, но этот тест JSperf, как правило, показывает, что чем больше проходит времени, тем больше includes()
будет быстрее, чем indexOf
(я думаю, он будет оптимизирован и дальше).
ИМХО, я также предпочитаю писать if (arr.includes(el)) {}
поскольку он более понятен и более понятен, чем if (arr.indexOf(el) !== -1) {}
.indexOf()
и .includes()
могут использоваться для поиска элемента в массиве или для поиска символа/подстроки в данной строке.
(Ссылка на спецификацию ECMAScript)
indexOf
использует строгое равенство Сравнение тогда includes
в includes
используют SameValueZero алгоритм. По этой причине возникают следующие два отличия.
Как указал Феликс Клинг, поведение отличается в случае NaN
.
let arr = [NaN];
arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
undefined
.let arr = [ , , ];
arr.indexOf(undefined); // returns -1; meaning undefined is not present
arr.includes(undefined); // returns true
(Ссылка на спецификацию ECMAScript)
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 и поэтому поддерживаются всеми браузерами.
Концептуально вам следует использовать indexOf, когда вы хотите использовать positionOffode, просто дайте вам извлечь значение или работать с массивом, то есть с помощью среза, сдвига или сплита после того, как вы получите позицию элемента. С другой стороны, Use Array.includes только для того, чтобы знать, находится ли значение внутри массива, а не позиция, потому что вам это неинтересно.