JavaScript/Objekte/Array/includes
Die von Array.prototype vererbte Methode includes prüft, ob in dem Array auf dem sie aufgerufen wurde ein bestimmter Wert enthalten ist und gibt als Ergebnis einen booleschen Wert zurück. Bei includes handelt es sich um eine generische Methode, sie kann also auch im Kontext von Objekten aufgerufen werden, die keine Arrays sind.
Syntax
Array.prototype.includes(searchElement[, fromIndex])
Writable | true |
Enumerable | false |
Configurable | true |
Prototyp
Eigenschaften
Inhaltsverzeichnis
Beschreibung
Die Methode erwartet als ersten Parameter den Wert, nach dem das Array durchsucht werden soll. Der optionale zweite Parameter bestimmt den Startindex für die Suche. Wird der gesuchte Wert in dem Array gefunden, dann wird der boolesche Wert true zurückgegeben, sonst der Wert false. Ist der gesuchte Wert in dem Array mehrfach vorhanden, wird die Suche bei der ersten Übereinstimmung beendet.
const array = [16, 32, 64, 128];
console.log(array.includes(64)); // true
Wenn wie in dem Beispiel oben kein Argument für den optionalen zweiten Parameter übergeben wird, dann wird als Standardwert für den Startindex Null verwendet. Das heißt, in diesem Fall wird das ganze Array nach dem Wert durchsucht, der als erstes Argument übergeben wurde.
const planets = ['Neptune', 'Jupiter', 'Saturn'];
console.log(planets.includes( )); // false
delete planets[1];
console.log(planets.includes( )); // true
Wird die Methode includes ohne Argumente aufgerufen, dann wird der erste Parameter standardmäßig mit dem Wert undefined initialisiert und entsprechend geprüft, ob in dem Array ein Element mit diesem Wert existiert. Dies ist bei der ersten Prüfung in dem Beispiel oben nicht der Fall, weshalb hier false der Rückgabewert ist. Wird allerdings ein Element des Arrays mit dem Operator delete gelöscht, dann rücken die nachfolgenden Elemente nicht auf um die Lücke zu schließen, sondern es wird lediglich der Wert des gelöschten Elementes auf undefined gesetzt. In diesem Fall ergibt die Prüfung also true.
const stars = ['Arcturus', 'Spica', 'Orionis'];
stars.splice(1, 1);
console.log(stars); // [Arcturus, Orionis]
console.log(stars.includes(undefined)); // false
Es ist allerdings ohnehin nicht empfehlenswert, Elemente eines Arrays mit dem Operator zu Löschung von Objekteigenschaften zu entfernen. Hierzu sollte immer die Methode splice verwendet werden, denn gegebenenfalls entstehende Lücken im Index werden bei Verwendung dieser Methode geschlossen. Sie ermöglicht es darüber hinaus auch, mehr als ein Element zu entfernen oder ein oder mehrere Elemente des Arrays zu ersetzten.
const array = [2, 4, 8, NaN];
console.log(array.some(item => item === NaN)); // false
console.log(array.includes(NaN)); // true
Beim Gebrauch der Methode includes ist weiter zu berücksichtigen, dass bei dem Vergleich der Werte des Arrays mit dem gesuchten Wert der Algorithmus Same Value Zero verwendet wird, das heißt, anders als bei der Prüfung auf Strict Equality wird hier auch dann der Wert true zurückgegeben, wenn der gesuchte Wert NaN ist. Da selbst die Prüfung auf strenge Gleichheit bei NaN false ergibt, muss normalerweise unter Verwendung der eingebauten Methode isNaN geprüft werden, ob es sich bei einem Wert um NaN handelt.
const planets = ['Mercury', 'Venus', 'Earth', 'Mars'];
console.log(planets.includes('Venus', 2)); // false
console.log(planets.includes('Earth', 2)); // true
Durch Übergabe eines Arguments für den optionalen zweiten Parameter der Methode includes kann der Index bestimmt werden, an dem die Suche beginnen soll. Wird also wie in dem Beispiel oben beim Aufruf der Wert 2 übergeben, dann ist das Element an der Indexposition 2 das erste Element, das mit dem gesuchten Wert verglichen wird. Das Ende der Suche markiert grundsätzlich das Element mit dem höchsten Index, also der letzte Eintrag in dem Array.
const numbers = [2, 3, 5, 7];
console.log(numbers.length); // 4
console.log(numbers.includes(5, 4)); // false
Ist der als zweites Argument übergebene Wert größer als die von der Eigenschaft length repräsentierte Anzahl der in dem Array enthaltenen Elemente, dann wird von der Methode includes grundsätzlich der boolesche Wert false zurückgegeben. Das Array wird also nur dann durchsucht, wenn der Startindex mindestens um Eins kleiner ist als die Länge des Arrays.
Relativer Wert für den Startindex
Wird der Methode includes als zweites Argument ein numerischer Wert übergeben, der kleiner ist als Null, dann wird die Länge des Arrays zu diesem Wert addiert und das Ergebnis als Startwert verwendet, sofern dieses größer oder gleich Null ist. Sonst wird die Suche standardmäßig an der ersten Indexposition des Arrays begonnen.
const satellites = ['Ganymede', 'Callisto', 'Thebe'];
console.log(satellites.includes('Ganymede', -2)); // false
console.log(satellites.includes('Thebe', -2)); // true
In dem Beispiel oben wird als zweites Argument jeweils der negative Wert -2 übergeben. Zu diesem Wert wird nun die Anzahl der in dem Array enthaltenen Elemente hinzugezählt, also 3, was im Ergebnis den Wert 1 ergibt. Die Suche wird hier demnach bei dem Element begonnen, das den Index 1 hat. Entsprechend ergibt die erste Suche mittels includes den Wert false, da der gesuchte Wert in dem Array nur bei dem Element mit dem Index 0 vorkommt.
const array = [true, false, null];
console.log(array.includes(true, -5)); // true
Wird für den Startindex ein Wert angegeben, der selbst nach der Addtion mit dem Wert der Eigenschaft length immer noch kleiner ist als 0, dann wird dieser ignoriert und die Suche bei dem Element mit dem Index 0 begonnen. In diesem Fall wird also grundsätzlich das ganze Array durchsucht.
Typumwandlungen
Auf den Wert des zweiten Parameters der Methode includes wird grundsätzlich die abstrakte Operation ToInteger angewendet, nach deren Regeln zum Beispiel der Wert NaN durch 0 ersetzt wird.
console.log([1, 2, 3].includes(2, NaN)); // true
console.log([4, 5, 6].includes(5, Infinity)); // false
console.log([7, 8, 9].includes(8, -Infinity)); // true
Wird als zweites Argument der Wert Infinity übergeben, dann werden auf diesen die allgemeinen, oben beschriebenen Regeln angewendet, also je nach Vorzeichen entweder der Startindex 0 verwendet, oder der Wert der Eigenschaft length des Arrays. Entsprechend wird bei negativer Unendlichkeit das ganze Array durchsucht und bei positiver Unendlichkeit passiert nichts.
const array = ['Charon', 'Hydra', 'Styx'];
console.log(array.includes('Charon', -2.8)); // false
Handelt es sich bei dem für den Startindex übergebenen Wert um eine gebrochene Zahl, dann wird nach den Regeln der Operation ToInteger das Ergebnis der auf dem Absolutbetrag des Wertes ausgeführten Abrundungsfunktion zurückgegeben.
In dem Beispiel oben wird von includes also schließlich der Wert false zurückgegeben, denn der für den Startindex übergebene negative Wert besitzt den Absolutbetrag 2.8, was abgerundet 2 ergibt. Weil beim Rückgabewert der Operation ToInteger das Vorzeichen allerdings nicht geändert wird, ist das Ergebnis hier immer noch negativ, weshalb die Länge des Arrays hinzugezählt wird. Der verwendete Index für den Start der Suche ist in diesem Fall also 1, wohingegen der gesuchte Wert nur bei dem Element mit dem Index 0 zu finden gewesen wäre.
console.log([4, 8, 16, 32].includes(4, true)); // false
console.log(['alpha', 'beta'].includes('alpha', false)); // true
console.log([64, 128, 256].includes(64, null)); // true
Wird der Methode ein Wert für den Startindex gegeben der nicht vom Datentyp Number ist, dann wird keine Ausnahme geworfen sondern wie üblich versucht, diesen Wert in eine Zahl zu konvertieren, was nach den Regeln der abstrakten Operation ToNumber zum Beispiel für den booleschen Wert true die Zahl 1 ergibt und für false die Zahl 0, ebenso wie es bei dem primitiven Wert null der Fall ist.
Generische Verwendung
Die Verwendung der Methode includes ist nicht auf Arrays beschränkt, sondern sie kann auch im Kontext von anderen Objekten aufgerufen werden. Dies kann beispielsweise mit der Methode call bewerkstelligt werden, welche von Function.prototype an die Methode includes vererbt wird. Die Methode call erwartet als erstes Argument das Objekt, in dessen Kontext die jeweilige Funktion aufgerufen werden soll und alle weiteren an call übergebenen Argumente werden an diese Funktion weitergereicht.
function test ( ) {
return Array.prototype.includes.call(arguments, 16, 1);
}
console.log(test(8, 16, 32)); // true
Auf diese Weise kann also zum Beispiel das exotische Objekt arguments mittels includes durchsucht werden, welches die an eine Funktion überebenen Argumente beinhaltet und bei dem es sich nicht um ein Array handelt. Statt die Methode includes direkt auf Array.prototype anzusprechen wie in dem Beispiel oben, könnte zu diesem Zweck aber natürlich auch ein leeres Arrayliteral verwendet werden.
Eigene Eigenschaften
Die Methode includes besitzt zwei eigene Eigenschaften, nämlich name und length. Der Wert der Eigenschaft name ist die Zeichenkette includes, also der Name der Methode und die Werte der internen Attribute dieser Eigenschaft sind false für Writable, false für Enumerable und true für Configurable. Die Eigenschaft ist also standardmäßig schreibgeschützt, kann aber unter Verwendung von Methoden wie zum Beispiel defineProperty von Object verändert werden.
const includes = Array.prototype.includes;
console.log(Object.getOwnPropertyNames(includes)); // [length, name]
console.log(includes.name); // includes
Die Eigenschaft length der Methode includes hat den Wert 1, da die Funktion nur über einen formalen Parameter verfügt, welcher den Wert erwartet, nach dem das Array durchsucht werden soll. Optionale Parameter werden bei der Berechnung der Länge einer Funktion ebenso wie Restparameter grundsätzlich nicht berücksichtigt.
const length = [ ].includes.length;
console.log(length); // 1
Die Werte der internen Attribute der Eigenschaft length sind dieselben wie bei der Eigenschaft name, also false für Writable, false für Enumerable und true für Configurable. Auch bei dieser Eigenschaft kann der Wert also nicht durch einfache Zuweisung (Assignment), sondern nur durch Definition verändert werden.
Beispiel für Polyfill
Da die Methode includes erst seit ECMAScript 2016 offiziell standardisiert ist und sie zum Zeitpunkt der Erstellung dieses Artikels noch nicht von allen wichtigen Ausführungsumgebungen unterstützt wird, sei im Folgenden ein Beispiel für ein Polyfill gegeben. Dabei wird zunächst geprüft, ob eine Methode mit dem Namen includes auf Array.prototype definiert ist. Wenn das nicht der Fall ist, wird eine entsprechende Methode angelegt.
if (!Array.prototype.includes) {
Array.prototype.includes = function includes (searchElement) {
if (this == null) {
throw new TypeError('this is null or undefined');
}
var object = Object(this),
length = object.length >>> 0;
if (length === 0) {
return false;
}
var start = arguments[1] >> 0,
key = start < 0 ? Math.max(start + length, 0) : start,
currentElement;
while (key < length) {
currentElement = object[key];
if (searchElement === currentElement
|| (searchElement !== searchElement
&& currentElement !== currentElement)) {
return true
}
key ++;
}
return false;
};
}
Der Stand der Unterstützung der Methode bei einer großen Auswahl an Ausführungsumgebungen kann darüber hinaus durch einen Blick auf die Tabelle zur Kompatibilität von Kangax in Erfahrung gebracht werden.
Weblinks
- ECMAScript 2017 (7th Edition, ECMA-262 Draft): Array.prototype.includes
- ECMAScript 2017 (7th Edition, ECMA-262 Draft): SameValueZero
- ECMAScript 2017 (7th Edition, ECMA-262 Draft): ToInteger