Array.prototype.includes vs. Array.prototype.indexOf


112

Окрім покращеної читабельності, чи є якась перевага includesнад indexOf? Вони здаються мені ідентичними.

Яка різниця між цим

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

І це?

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

12
includesмає набагато гіршу підтримку браузера.
Квентін

4
Зауважте, що includesце не є частиною ES6 / ES2015. Це пропозиція для наступної версії ECMAScript і буде додана цього року.
Фелікс Клінг

4
просто хотів також зазначити, що includesНЕ підтримується в IE
ZvKa

Відповіді:


138

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)істинним.

Таким чином, ця пропозиція вирішує обидві проблеми, що спостерігаються в існуючому коді.

Додатково додаємо fromIndexпараметр, подібний до Array.prototype.indexOfта String.prototype.includes, за послідовністю.


Додаткова інформація:


1
Тільки половина правди. Крім того, різні: Відсутні елементи розглядаються як undefinedшлях .includes()і не розглядаються .indexOf().
Роберт Сімер

11

Якщо ви замислюєтесь про виступи, на даний момент indexOf швидше, але цей тест JSperf, як правило, показує, що чим більше пройде часу, тим includes()швидше буде indexOf(напевно, він буде оптимізований далі).

ІМХО, я також вважаю за краще писати, if (arr.includes(el)) {}оскільки це зрозуміліше і більш ретельне, ніжif (arr.indexOf(el) !== -1) {}


1
Здається, різниця в продуктивності не така очевидна. Мій мобільний Firefox показує, що indexOf насправді швидше. Деякі версії Chrome діють так само ... Але різниця здається незначною у сучасних реалізаціях.
Nux

8

.indexOf() і .includes() методи можуть бути використані для пошуку елемента в масиві або для пошуку символу / підрядка в заданому рядку.

Використання в масиві

( Посилання на специфікацію ECMAScript)

  1. indexOfвикористовує суворе порівняння рівності, тоді як 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, він викине виняток.
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але в реальності це не має великої різниці і є незначним.

Історія

String.prototype.includes()була представлена ​​в ECMAScript 2015, тоді як вона Array.prototype.includes()була представлена ​​в ECMAScript 2016. Що стосується підтримки браузера, використовуйте їх з розумом.

String.prototype.indexOf()і Array.prototype.indexOf()вони присутні у виданні ES5 ECMAScript ES5 і тому підтримуються всіма браузерами.


indexOfдає trueпісля явного встановлення undefinedв масив: let arr=[undefined];або let arr=[];arr[0]=undefined;Заразarr.indexOf(undefined) === 0
Джей

Ви єдиний, хто вказує на різницю з undefined: Причина полягає в тому, що .includesтрактує відсутні елементи як undefined, а .indexOf()ігнорує їх. Ви також можете "створити" відсутні елементи за допомогою arr[number beyond length] = whatever.
Роберт Сімер

Ніхто не просив рядків, але ваші зауваження говорять про те, що .includes()їдять лише рядки. Насправді обидва методи примушують будь-що до струни настільки добре, наскільки вони можуть. Regex спеціально виключений в якості аргументу , .includes()щоб дозволити для майбутніх доповнень до стандарту в відповідно до поточного проектом.
Роберт Сімер

4

Концептуально вам слід використовувати indexOf, коли ви хочете використовувати позицію indexOf, просто дайте вам отримати значення або працювати над масивом, тобто використовувати зріз, зсув або розбиття після того, як ви отримали положення елемента. З іншого боку, Use Array.includes only to know if value is in the масив, а не позиція, тому що вам це не важливо.


0

indexOf()і includes()обидва можуть використовуватися для пошуку елементів у масиві, однак кожна функція дає різні повернені значення.

indexOfповертає число ( -1якщо елемент не присутній у масиві, або положення масиву, якщо елемент присутній).

includes()повертає булеве значення ( trueабо false).


Привіт Круті, на це питання вже відповіли, і він прийняв відповідь. Крім того, ви можете бачити, як ваша відповідь містить лише інформацію, вже сказану в інших відповідях. Питання, врешті-решт, вже 4 роки. Будь ласка, надайте вказівки щодо найновіших питань або без відповідей. Дякую
leonardfactory
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.