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

112

Gibt es über die verbesserte Lesbarkeit hinaus einen Vorteil includesgegenüber indexOf? Sie scheinen mir identisch zu sein.

Was ist der Unterschied zwischen diesen

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

Und das?

var y = [1,2,3].includes(1); //true
Matt
quelle
12
includeshat viel schlechtere Browser-Unterstützung.
Quentin
4
Beachten Sie, dass dies includesnicht Teil von ES6 / ES2015 ist. Es ist ein Vorschlag für die nächste Version von ECMAScript und wird in diesem Jahr hinzugefügt.
Felix Kling
4
includes
Ich

Antworten:

138

tl; dr: NaN wird anders behandelt:

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

Aus dem Vorschlag :

Motivation

Bei Verwendung von ECMAScript-Arrays ist es häufig erwünscht, festzustellen, ob das Array ein Element enthält. Das vorherrschende Muster hierfür ist

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

mit verschiedenen anderen Möglichkeiten, zB arr.indexOf(el) >= 0oder sogar ~arr.indexOf(el).

Diese Muster weisen zwei Probleme auf:

  • Sie können nicht "sagen, was Sie meinen": Anstatt zu fragen, ob das Array ein Element enthält, fragen Sie nach dem Index des ersten Auftretens dieses Elements im Array und vergleichen es dann oder drehen es ein wenig, um es zu bestimmen die Antwort auf Ihre eigentliche Frage.
  • Sie scheitern daran NaN, wie indexOfStrict Equality Comparison und damit verwendet [NaN].indexOf(NaN) === -1.

Vorgeschlagene Lösung

Wir schlagen die Hinzufügung einer Array.prototype.includesMethode vor, so dass die obigen Muster wie folgt umgeschrieben werden können

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

Dies hat fast die gleiche Semantik wie oben, außer dass der SameValueZero-Vergleichsalgorithmus anstelle des Strict Equality Comparison verwendet wird, wodurch dies [NaN].includes(NaN)wahr wird.

Somit löst dieser Vorschlag beide Probleme, die im vorhandenen Code auftreten.

Wir fügen zusätzlich einen fromIndexParameter ähnlich Array.prototype.indexOfund String.prototype.includesfür Konsistenz.


Weitere Informationen:

Felix Kling
quelle
1
Nur die halbe Wahrheit. Auch anders: Fehlende Elemente werden als undefinedvon behandelt und von .includes()nicht berücksichtigt .indexOf().
Robert Siemer
11

Wenn Sie sich über die Leistung wundern, ist indexOf im Moment schneller, aber dieser JSperf- Test zeigt tendenziell, dass mehr Zeit vergeht , mehr includes()schneller alsindexOf (ich denke, es wird weiter optimiert).

IMHO schreibe ich auch lieber, if (arr.includes(el)) {}da es klarer und wartbarer ist alsif (arr.indexOf(el) !== -1) {}

538ROMEO
quelle
1
Der Leistungsunterschied scheint nicht so offensichtlich zu sein. Mein mobiler Firefox zeigt, dass indexOf tatsächlich schneller ist. Einige Chrome-Versionen verhalten sich gleich ... Aber der Unterschied scheint in den heutigen Implementierungen ohnehin vernachlässigbar.
Nux
8

.indexOf() und .includes() Methoden können verwendet werden, um nach einem Element in einem Array zu suchen oder um nach einem Zeichen / Teilstring in einer bestimmten Zeichenfolge zu suchen.

Verwendung im Array

( Link zur ECMAScript-Spezifikation)

  1. indexOfverwendet Strict Equality Comparison, während includesder SameValueZero- Algorithmus verwendet wird. Aus diesem Grund ergeben sich die folgenden zwei Unterschiede.

  2. Wie Felix Kling betonte, ist das Verhalten bei NaN.

let arr = [NaN];

arr.indexOf(NaN); // returns -1; meaning NaN is not present
arr.includes(NaN); // returns true
  1. Das Verhalten ist auch im Fall von anders undefined.
let arr = [ , , ];

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

Verwendung in String

( Link zur ECMAScript-Spezifikation)

  1. Wenn Sie ein RegExp an übergeben indexOf, wird das RegExp als Zeichenfolge behandelt und der Index der Zeichenfolge zurückgegeben, falls gefunden. Wenn Sie jedoch ein RegExp an übergeben includes, wird eine Ausnahme ausgelöst .
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

Performance

Wie 538ROMEO hervorhob , includeskann es ein wenig (sehr winzig) etwas langsamer sein (da es als erstes Argument nach einem regulären Ausdruck suchen muss) alsindexOf aber in Wirklichkeit macht dies keinen großen Unterschied und ist vernachlässigbar.

Geschichte

String.prototype.includes()wurde in ECMAScript 2015 eingeführt, während Array.prototype.includes()es in ECMAScript 2016 eingeführt wurde. Verwenden Sie die Browserunterstützung mit Bedacht.

String.prototype.indexOf()und Array.prototype.indexOf()sind in der ES5-Ausgabe von ECMAScript vorhanden und werden daher von allen Browsern unterstützt.

Srishti
quelle
indexOfgibt truenach expliziter Einstellung undefinedin ein Array: let arr=[undefined];oder let arr=[];arr[0]=undefined;Nowarr.indexOf(undefined) === 0
Jay Dadhania
Sie sind der einzige, der den Unterschied anzeigt mit undefined: Der Grund ist, dass .includesfehlende Elemente als behandelt werden undefined, während sie .indexOf()ignoriert werden. Sie können auch fehlende Elemente mit erstellen arr[number beyond length] = whatever.
Robert Siemer
Niemand hat nach Saiten gefragt, aber Ihre Bemerkungen legen nahe, dass .includes()nur Saiten gegessen werden. In Wirklichkeit zwingen beide Methoden alles so gut wie möglich zu einer Saite. Regex wird ausdrücklich als Argument ausgeschlossen .includes(), um zukünftige Ergänzungen des Standards gemäß dem aktuellen Entwurf zu ermöglichen.
Robert Siemer
3

Konzeptionell sollten Sie indexOf verwenden, wenn Sie die Position indexOf verwenden möchten. Geben Sie dazu einfach den Wert zu extrahieren oder über das Array zu operieren, dh verwenden Sie Slice, Shift oder Split, nachdem Sie die Position des Elements erhalten haben. Auf der anderen Seite verwendet Use Array.includes nur, um zu wissen, ob sich der Wert innerhalb des Arrays befindet und nicht die Position, da Sie sich nicht darum kümmern.

Sebastian Gomez
quelle
0

indexOf()und includes()beide können verwendet werden, um Elemente in einem Array zu finden, jedoch liefert jede Funktion unterschiedliche Rückgabewerte.

indexOfGibt eine Zahl zurück ( -1wenn das Element nicht im Array vorhanden ist, oder die Array-Position, wenn das Element vorhanden ist).

includes()Gibt einen booleschen Wert ( trueoder false) zurück.

Kruti
quelle
Hallo Kruti, diese Frage wurde bereits beantwortet und hat eine akzeptierte Antwort. Außerdem können Sie sehen, dass Ihre Antwort nur Informationen enthält, die bereits in anderen Antworten angegeben wurden. Die Frage ist am Ende schon 4 Jahre alt. Bitte geben Sie Hinweise zu den neuesten oder unbeantworteten Fragen. Vielen Dank
leonardfactory