Abschnitt 6 · Lektion 4
Suchen und prüfen
Eine Liste durchsuchen könntest du mit einer Schleife und einem break, so wie in der letzten Lektion. Für die häufigsten Fälle gibt es fertige Methoden, und die sind kürzer, klarer und hören von selbst auf, sobald die Antwort feststeht.
Nach einem Wert suchen
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> const zahlen = [3, 5, 1, 7, 12];
// includes beantwortet die Ja-Nein-Frage.
console.log("Ist 7 dabei?", zahlen.includes(7));
console.log("Ist 4 dabei?", zahlen.includes(4));
// indexOf liefert die Position, und -1 heißt nicht gefunden.
console.log("7 steht bei:", zahlen.indexOf(7));
console.log("4 steht bei:", zahlen.indexOf(4));
// Deshalb prüft man auf -1 und nicht auf einen falschen Wert:
// die 0 wäre die erste Position und damit ein Treffer.
console.log("3 steht bei:", zahlen.indexOf(3));
console.log("Falsch geprüft:", zahlen.indexOf(3) ? "gefunden" : "nicht gefunden");
console.log("Richtig geprüft:", zahlen.indexOf(3) !== -1 ? "gefunden" : "nicht gefunden"); includes beantwortet die Ja-Nein-Frage und liefert true oder false. Das ist die Methode, die du am häufigsten brauchst.
indexOf liefert die Position, und wenn nichts gefunden wurde, die -1.
Auf -1 muss man ausdrücklich prüfen. Die naheliegende Abkürzung ist eine Falle: if (liste.indexOf(x)) besteht nicht, wenn x an erster Stelle steht, denn 0 ist falsy, wie du aus Lektion 3.3 weißt. Der Treffer an Position null sieht damit aus wie kein Treffer.
Deshalb entweder !== -1 schreiben oder gleich includes nehmen. Letzteres gibt es genau aus diesem Grund.
Nach einer Bedingung suchen
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> const zahlen = [3, 5, 1, 7, 12, 9, 20];
// find bekommt eine Funktion statt eines Werts und gibt den
// ersten Eintrag zurück, für den sie true liefert.
console.log("Erste über 10:", zahlen.find((zahl) => zahl > 10));
console.log("Erste gerade:", zahlen.find((zahl) => zahl % 2 === 0));
// findIndex liefert stattdessen die Position.
console.log("Position der ersten über 10:", zahlen.findIndex((zahl) => zahl > 10));
// Ohne Treffer: find liefert undefined, findIndex liefert -1.
console.log("Über 100:", zahlen.find((zahl) => zahl > 100));
console.log("Position über 100:", zahlen.findIndex((zahl) => zahl > 100)); Oft kennt man den gesuchten Wert nicht, sondern nur eine Eigenschaft: die erste Zahl über hundert, der erste Eintrag mit mehr als zehn Zeichen.
Dafür ist find da. Es bekommt eine Funktion statt eines Werts, ruft sie je Eintrag auf und gibt den ersten zurück, für den sie einen wahren Wert liefert. Das ist wieder der Callback aus Lektion 5.7.
findIndex tut dasselbe und liefert die Position statt des Werts.
Ohne Treffer liefert find ein undefined und findIndex eine -1. Beide Werte muss man abfangen, sonst rechnet man später mit undefined weiter, und das Ergebnis ist das NaN aus Lektion 5.2.
Reicht einer oder müssen alle
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> const zahlen = [3, 5, 1, 7, 12];
// some: reicht einer? every: müssen alle?
console.log("Mindestens eine über 10:", zahlen.some((zahl) => zahl > 10));
console.log("Alle über 10:", zahlen.every((zahl) => zahl > 10));
console.log("Alle über 0:", zahlen.every((zahl) => zahl > 0));
// Bei einer leeren Liste ist some immer false und every immer
// true. Das wirkt komisch und ist die einzig widerspruchsfreie
// Antwort: Es gibt keinen Eintrag, der die Bedingung verletzt.
const leer = [];
console.log("Leer, some:", leer.some((zahl) => zahl > 0));
console.log("Leer, every:", leer.every((zahl) => zahl > 0)); some fragt: Gibt es mindestens einen, für den die Bedingung stimmt?
every fragt: Stimmt sie für alle?
Beide liefern true oder false und hören auf, sobald die Antwort feststeht. some beim ersten Treffer, every beim ersten Gegenbeispiel. Bei einer Liste mit zehntausend Einträgen und einem Treffer ganz vorn ist das der ganze Unterschied.
Ein Sonderfall, der beim ersten Mal irritiert: Bei einer leeren Liste ist some immer false und every immer true. Das ist keine Willkür, sondern die einzige widerspruchsfreie Antwort. Es gibt keinen Eintrag, der die Bedingung erfüllt, und es gibt auch keinen, der sie verletzt.
Wenn der Vergleich nicht greift
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> // Bei Zahlen und Texten vergleicht includes den Wert.
console.log([1, 2, 3].includes(2));
// Bei Listen und Objekten vergleicht es, ob es dasselbe Ding ist.
const paare = [[1, 2], [3, 4]];
console.log("Gleich aussehend:", paare.includes([1, 2]));
// Denn schon der einfache Vergleich sagt nein.
console.log("[1,2] === [1,2] ergibt", [1, 2] === [1, 2]);
// Mit derselben Liste sagt es ja.
const eins = [1, 2];
const nochmal = [eins, [3, 4]];
console.log("Dieselbe Liste:", nochmal.includes(eins));
// Und mit einer Bedingung geht es immer.
console.log("Mit find:", paare.find((paar) => paar[0] === 1 && paar[1] === 2)); includes und indexOf vergleichen mit ===, und bei Zahlen und Texten ist das genau das, was man will.
Bei Listen und Objekten nicht. Dort fragt === nicht „sehen die gleich aus”, sondern „ist das dasselbe Ding”. Zwei getrennt angelegte Listen mit demselben Inhalt sind zwei Dinge, und deshalb sagt includes dort nein.
Das ist einer der Punkte, an denen JavaScript-Anfänger am längsten rätseln, und in Abschnitt 7 wird er noch wichtiger, denn Objekte verhalten sich genauso.
Der Ausweg ist immer derselbe: Statt nach dem Wert zu suchen, suchst du mit einer Bedingung. find und findIndex fragen nicht nach Gleichheit, sondern nach dem, was du prüfen willst, und damit ist das Problem weg.
Zum Mitnehmen
includes und indexOf suchen nach einem Wert. find, some und every nehmen stattdessen eine Bedingung entgegen, und deshalb finden sie auch das, was man nicht genau kennt.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.