Array.prototype.includes a Array.prototype.indexOf

112

Poza poprawioną czytelnością jest jeszcze coś do includespokonaniaindexOf ? Wydają mi się identyczne.

Jaka jest różnica między tym

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

I to?

var y = [1,2,3].includes(1); //true
Matt
źródło
12
includesma znacznie gorszą obsługę przeglądarki.
Quentin
4
Należy pamiętać, że includesnie jest to część ES6 / ES2015. Jest to propozycja kolejnej wersji ECMAScript i zostanie dodana w tym roku.
Felix Kling
4
chciałem tylko wspomnieć, że includesw IE NIE jest obsługiwane
ZvKa

Odpowiedzi:

138

tl; dr: NaN jest traktowany inaczej:

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

Z propozycji :

Motywacja

Podczas korzystania z tablic ECMAScript często pożądane jest określenie, czy tablica zawiera element. Dominującym wzorcem jest to

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

z różnymi innymi możliwościami, np. arr.indexOf(el) >= 0lub nawet ~arr.indexOf(el).

Te wzorce mają dwa problemy:

  • Nie potrafią „powiedzieć, co masz na myśli”: zamiast pytać, czy tablica zawiera element, pytasz, jaki jest indeks pierwszego wystąpienia tego elementu w tablicy, a następnie porównujesz go lub przekręcasz bitowo, aby określić odpowiedź na twoje aktualne pytanie.
  • Zawodzą NaN, ponieważ indexOfużywa ścisłego porównania równości, a tym samym [NaN].indexOf(NaN) === -1.

Proponowane rozwiązanie

Proponujemy dodanie Array.prototype.includesmetody, dzięki której powyższe wzorce można przepisać jako

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

Ma prawie taką samą semantykę jak powyżej, z tym wyjątkiem, że używa algorytmu porównania SameValueZero zamiast Strict Equality Compare, dzięki czemu [NaN].includes(NaN) prawdziwy.

Zatem ta propozycja rozwiązuje oba problemy widoczne w istniejącym kodzie.

Dodatkowo dodajemy fromIndexparametr podobny do Array.prototype.indexOfi String.prototype.includesdla spójności.


Dalsza informacja:

Felix Kling
źródło
1
Tylko połowa prawdy. Również inna: brakujące elementy są traktowane jako undefinedprzez .includes()i nie są uważane za .indexOf().
Robert Siemer
11

Jeśli zastanawiasz się nad wydajnością, na razie indexOf jest szybszy, ale ten test JSperf ma tendencję do pokazywania, że ​​więcej czasu mija, więcej includes()będzie szybsze niż indexOf(myślę, że zostanie zoptymalizowany dalej).

IMHO, ja też wolę pisać, if (arr.includes(el)) {}ponieważ jest jaśniejszy i łatwiejszy w utrzymaniu niżif (arr.indexOf(el) !== -1) {}

538ROMEO
źródło
1
Wygląda na to, że różnica w wydajności nie jest tak oczywista. Mój mobilny Firefox pokazuje, że indexOf jest w rzeczywistości szybszy. Niektóre wersje Chrome działają tak samo ... Ale różnica w dzisiejszych implementacjach i tak wydaje się nieistotna.
Nux
8

.indexOf()i .includes()metod można użyć do wyszukania elementu w tablicy lub do wyszukania znaku / podłańcucha w danym ciągu.

Wykorzystanie w Array

( Link do specyfikacji ECMAScript)

  1. indexOfużywa ścisłego porównania równości, podczas gdy includesużywa algorytmu SameValueZero . Z tego powodu pojawiają się następujące dwie różnice.

  2. Jak zauważył Felix Kling , zachowanie jest inne w przypadku NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Zachowanie jest również inne w przypadku undefined.
let arr = [ , , ];

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

Użycie w ciągu znaków

( Link do specyfikacji ECMAScript)

  1. Jeśli przekażesz RegExp do indexOf, potraktuje RegExp jako ciąg i zwróci indeks ciągu, jeśli zostanie znaleziony. Jednak jeśli przekażesz RegExp do includes, zgłosi wyjątek.
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

Występ

Jak wskazał 538ROMEO , includesmoże być trochę (bardzo malutki) nieco wolniejszy (ponieważ musi sprawdzić regex jako pierwszy argument) niż, indexOfale w rzeczywistości nie robi to dużej różnicy i jest pomijalne.

Historia

String.prototype.includes()zostało wprowadzone w ECMAScript 2015, natomiast Array.prototype.includes()zostało wprowadzone w ECMAScript 2016. Jeśli chodzi o obsługę przeglądarek, korzystaj z nich mądrze.

String.prototype.indexOf()i Array.prototype.indexOf()są obecne w wersji ES5 ECMAScript i dlatego są obsługiwane przez wszystkie przeglądarki.

Srishti
źródło
indexOfdaje truepo jawnym ustawieniu undefinedw tablicy: let arr=[undefined];lub let arr=[];arr[0]=undefined;Terazarr.indexOf(undefined) === 0
Jay Dadhania
Jesteś jedyną osobą wskazującą na różnicę undefined: Powodem jest to, że .includestraktuje brakujące elementy jako undefined, a .indexOf()ignoruje je. Możesz także „tworzyć” brakujące elementy za pomocą arr[number beyond length] = whatever.
Robert Siemer
Nikt nie prosił o struny, ale Twoje uwagi sugerują, że .includes()je tylko struny. W rzeczywistości obie metody zmuszają wszystko do stworzenia struny najlepiej, jak potrafią. Regex jest specyficznie wyłączona jako argument .includes()do umożliwienia przyszłych dodatków do standardu według obecnego projektu.
Robert Siemer
4

Koncepcyjnie powinieneś użyć indexOf, gdy chcesz użyć pozycji indexOf, aby po prostu wyodrębnić wartość lub operować na tablicy, tj. Używając slice, shift lub split po uzyskaniu pozycji elementu. Z drugiej strony, użyj Array.includes tylko po to, aby wiedzieć, czy wartość znajduje się wewnątrz tablicy, a nie w pozycji, ponieważ nie dbasz o to.

Sebastian Gomez
źródło
0

indexOf()i includes()mogą być używane do znajdowania elementów w tablicy, jednak każda funkcja zwraca inne wartości zwracane.

indexOfzwraca liczbę ( -1jeśli elementu nie ma w tablicy lub pozycję tablicy, jeśli element jest obecny).

includes()zwraca wartość logiczną ( truelub false).

Kruti
źródło
Cześć Kruti, na to pytanie już udzielono odpowiedzi i zaakceptowano odpowiedź. Ponadto możesz zobaczyć, że Twoja odpowiedź zawiera tylko informacje już podane w innych odpowiedziach. W końcu pytanie ma już 4 lata. Proszę podać wskazówki dotyczące najnowszych pytań lub pytań bez odpowiedzi. Dziękuję
leonardfactory