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

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:


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) {}


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.


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.


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).


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.