Start / Seminare / JavaScript Grundlagen & Modernes ECMAScript
Modul
Arrays, Objekte, Maps und Sets
6 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
JavaScript — Sammlungen
0:00 Einzelne Werte haben wir behandelt, Objekte auch. Jetzt geht es um die Frage, wie man viele davon organisiert — und die ist wichtiger, als sie klingt. Erfahrene Entwicklerinnen und Entwickler sagen gern: Die halbe Miete ist die Wahl der Datenstruktur. Passt sie zur Aufgabe, schreibt sich der Rest fast von selbst. Passt sie nicht, kämpfen Sie in jeder Zeile gegen Ihre eigene Entscheidung.
0:23 In diesem Modul lernen Sie vier Strukturen kennen und vor allem die Fragen, mit denen Sie zwischen ihnen wählen. Ein Thema zieht sich durch: verändern oder neu erzeugen.
Daten in Sammlungen
0:33 Sechs Kapitel. Wir beginnen mit dem Überblick und der Auswahlfrage — das ist der wichtigste Teil, auch wenn er am wenigsten nach Code aussieht. Dann Arrays im Detail, mit besonderem Blick auf die Methoden, die das Original verändern. Danach Suchen und Kopieren, wo moderne JavaScript-Versionen erfreulich aufgeräumt haben.
0:52 Objekte als Datenstruktur folgen, mit der Tücke der flachen Kopie. Und zum Schluss zwei Strukturen, die viele zu selten nutzen: Map und Set, samt den eingebauten Mengenoperationen.
Sammlungstypen im Überblick
1:04 Beginnen wir mit der Auswahl. Die Methodenlisten der einzelnen Strukturen können Sie jederzeit nachschlagen — die Frage, welche Struktur überhaupt passt, müssen Sie im Kopf haben. Vier Strukturen, vier Fragen. Eine Datenstruktur organisiert Daten für einen bestimmten Zweck — und die Betonung liegt auf dem Zweck. Es gibt keine beste Struktur, es gibt nur die passende.
1:27 Vier Fragen führen Sie zur Antwort. Zählt die Reihenfolge? Zählen Namen für die einzelnen Felder? Zählt Eindeutigkeit, soll also jeder Wert nur einmal vorkommen? Oder wird gezielt nach einem Schlüssel gesucht? Jede dieser Fragen zeigt auf eine andere Struktur. Gewöhnen Sie sich an, diese vier Fragen zu stellen, bevor Sie die erste Zeile schreiben. Das ist billiger als jeder spätere Umbau.
1:52 Die Tabelle ordnet die vier Fragen den vier Strukturen zu. Ein Array, wenn eine Reihenfolge gemeint ist — alle Beete des Gartens in der Reihenfolge, in der sie angelegt wurden. Ein Objekt, wenn benannte Felder zählen — ein einzelnes Beet mit Name, Fläche und Art. Eine Map, wenn Sie nachschlagen wollen, und zwar gezielt statt suchend.
2:12 Ein Set, wenn Doppelte verschwinden sollen. Der Fußtext ist praktisch der wichtigste Satz: In der Realität kombinieren Sie diese Strukturen. Ein Array aus Objekten ist das Standardmuster in praktisch jeder Anwendung — eine Liste von Datensätzen. Zwei Begriffe, die zusammengehören und oft verwechselt werden. Iterierbar ist ein Wert, über den man laufen kann — Arrays, Zeichenketten, Maps, Sets.
2:37 Der Iterator ist das Objekt, das dabei die eigentliche Arbeit macht und den jeweils nächsten Wert herausrückt. Denken Sie an ein Buch und ein Lesezeichen: Das Buch ist iterierbar, das Lesezeichen ist der Iterator. Die beiden unteren Punkte deuten auf ein Thema voraus, das uns in einem späteren Modul beschäftigen wird. Eifrige Verarbeitung baut sofort die ganze neue Sammlung.
2:59 Träge Verarbeitung erzeugt jeden Wert erst dann, wenn er gebraucht wird — was bei großen Datenmengen einen erheblichen Unterschied macht. Vier Aufgaben, vier Strukturen — und für jede den Grund nennen. Alle Beete des Gartens, ein einzelnes Beet, Beete nach Kennung, die Liste der vorkommenden Pflanzenarten. Schreiben Sie die Begründung wirklich hin, in einem Satz je Zuordnung: Reihenfolge, Namen, Schlüssel oder Eindeutigkeit.
3:25 Das klingt nach Trockenübung, ist aber genau die Denkarbeit, die man in Projekten überspringt — und die man dann teuer nachholt. Wer diese vier Fälle einmal sauber sortiert hat, erkennt sie später im echten Projekt wieder. Ein Objekt zu verwenden, wo die Reihenfolge zählt, führt zu Code, der bei kleinen Datenmengen funktioniert und bei größeren merkwürdig wird — auf die Reihenfolge von Objekteigenschaften sollte man sich nicht verlassen.
3:51 Ein Array zu durchsuchen, wo ein Schlüsselzugriff gemeint ist, funktioniert immer und wird bei wachsenden Daten immer langsamer. Doppelte von Hand herauszufiltern, ist Arbeit, die ein Set kostenlos erledigt. Und der letzte Punkt ist der eigentlich teure: die Struktur erst zu wählen, wenn der Code schon steht. Dann richtet sich die Struktur nach dem Code statt umgekehrt, und das geht selten gut.
Arrays
4:13 Jetzt die mit Abstand häufigste Struktur im Detail. Arrays sind schnell erklärt — ein Schlüsselwort begleitet uns dabei aber durch das ganze Kapitel und darüber hinaus: Mutation. Also die Frage, ob eine Methode das Original verändert. Ein Array ist eine geordnete Sammlung von Werten, und jeder Wert hat seine Position — den Index, gezählt ab null. Das kennen wir schon von den Zeichenketten.
4:37 Der zweite Satz ist der überraschende: Technisch ist ein Array ein Objekt. Deshalb meldet die Typabfrage auch nur „object" und hilft bei der Frage, ob etwas ein Array ist, kein Stück weiter. Das ist eine dieser historischen Eigenheiten, mit denen man leben muss. Es gibt eine eigene Prüffunktion dafür, und die sollten Sie sich merken — sie ist die einzige verlässliche Antwort.
5:00 Drei Dinge lohnen hier den Blick. Erstens die zweite Zeile mit dem viel zu hohen Index: Sie bekommen keinen Fehler, sondern undefined. Das ist dasselbe Verhalten wie bei fehlenden Objekteigenschaften und aus demselben Grund — ein Array ist ein Objekt. Bequem, aber es verschleiert Fehler. Zweitens die Zugriffsmethode mit dem negativen Index: minus eins liefert das letzte Element, ohne dass Sie mit der Länge rechnen müssen.
5:25 Und drittens der Block unten, der die Prüffrage klärt: Die eigene Prüffunktion sagt Ihnen die Wahrheit, die allgemeine Typabfrage nicht. Vier Methoden, ein gemeinsames Merkmal — sie alle verändern das Array, auf dem sie aufgerufen werden. Zwei arbeiten am Ende, zwei am Anfang, zwei fügen hinzu, zwei entfernen. Diese Symmetrie hilft beim Merken.
5:46 Wichtiger als die Namen ist aber die Konsequenz: Wenn zwei Programmteile auf dasselbe Array zeigen — und das passiert schnell, wie wir bei den Referenzen gesehen haben —, dann sieht der eine die Änderung des anderen. Ungewollt kann das zu Fehlern führen, die sehr weit weg von ihrer Ursache auffallen. Die Alternativen, die das Original in Ruhe lassen, kommen im nächsten Kapitel.
6:09 Machen Sie die Veränderung sichtbar: Länge vorher, Länge nachher, und dann benennen Sie, welche Variablen die Änderung mitbekommen. Der Trick steckt im Hinweis — legen Sie vorher mit der Drei-Punkt-Schreibweise eine Kopie an und vergleichen Sie beide. Sie sehen dann in einer einzigen Ausgabe den ganzen Unterschied: Das eine Array hat sich verändert, das andere nicht.
6:29 Dieses kleine Experiment ist die praktische Grundlage für alles, was in den funktionalen Modulen noch kommt. Nehmen Sie sich die fünf Minuten. Der Index ab eins ist der ewige Klassiker, und er begegnet Ihnen hier wieder. Der zweite Punkt ist heimtückischer: Ein zu hoher Index liefert undefined statt eines Fehlers, und wer damit weiterarbeitet, bekommt den Fehler erst später und woanders.
6:52 Die Typabfrage für die Array-Prüfung zu nehmen, liefert immer dieselbe nutzlose Antwort — nehmen Sie die eigene Prüffunktion. Und der letzte Punkt ist der praktisch folgenreichste: Eine anhängende Methode auf ein geteiltes Array anzuwenden, überrascht andere Programmteile. Sie sehen plötzlich einen Eintrag, den sie nie hinzugefügt haben.
Suchen und kopieren
7:12 Jetzt kommt eine der erfreulichsten Verbesserungen der letzten Jahre. JavaScript hat für seine mutierenden Methoden nicht-mutierende Zwillinge bekommen — und die sind in modernem Code die Standardwahl. Ein Vierklang, den Sie sich merken sollten. Zwei Gruppen von Methoden. Die Suchmethoden liefern entweder das erste passende Element selbst oder seinen Index — je nachdem, was Sie brauchen.
7:35 Die Kopiermethoden sind die eigentliche Neuerung: Sie erzeugen ein neues Array mit der gewünschten Änderung und lassen das Original in Ruhe. Und das Schönste daran ist die Benennung. Diese Methoden beginnen mit einem kleinen „to", und das ist kein Zufall, sondern ein Versprechen: Was mit to anfängt, verändert nichts. Wenn Sie diese Konvention einmal kennen, lesen Sie fremden Code deutlich schneller.
7:59 Hier sehen Sie das Standardmuster, von dem eben die Rede war: ein Array aus Objekten. Die Zeile mit der Prüffunktion ist eine kompakte Schreibweise für Funktionen, die wir in einem späteren Modul genauer behandeln — für heute lesen Sie sie einfach als „ist ein Kräuterbeet". Die drei Aufrufe unten unterscheiden sich in einem Detail mit praktischer Bedeutung: Der erste findet den ersten Treffer, der zweite sucht vom Ende her und findet den letzten.
8:24 Das brauchen Sie öfter, als man denkt — immer dann, wenn der jüngste Eintrag gemeint ist. Und die dritte Variante liefert nicht das Element, sondern seine Position. Diese Gegenüberstellung ist die praktischste Tabelle des Moduls. Links, was das Original verändert, rechts der Zwilling, der eine Kopie liefert. Die letzte Zeile ist die interessanteste: Sogar die direkte Zuweisung an eine Position hat eine Entsprechung bekommen, die ein neues Array zurückgibt.
8:51 Warum ist die rechte Spalte heute die Standardwahl? Weil sie eine Fehlerklasse ausschließt. Wenn niemand ein Array unter der Hand verändert, muss auch niemand damit rechnen — und Code, mit dem man nicht rechnen muss, ist Code, den man verstehen kann. Der Preis ist ein neues Array im Speicher, und der ist meistens vernachlässigbar.
9:10 Sortieren Sie ein Array, ohne den Zustand für andere Programmteile zu verändern. Der Nachweis: Geben Sie die Reihenfolge des Originals vor und nach dem Aufruf aus — sie muss identisch sein. Wenn Sie versehentlich die alte Methode erwischen, sehen Sie es sofort, und auch das ist ein guter Lerneffekt. Diese Übung wirkt klein, adressiert aber einen der häufigsten Fehler in echten Anwendungen: Eine Funktion, die eigentlich nur auswerten soll, verändert nebenbei ihre Eingabe.
9:38 Solche Nebenwirkungen aufzuspüren, kostet in großen Projekten Tage. Die alte Sortiermethode aufzurufen und die Nebenwirkung zu übersehen, ist genau der Fall aus der Aufgabe — sie sortiert das Original um, und zwar dauerhaft. Der zweite Punkt ist eine Frage der Absicht: Suchen Sie wirklich den ersten Treffer, oder war der letzte gemeint?
9:58 Beides gibt es, und die Methodennamen unterscheiden sich nur um ein Wort. Der dritte Punkt ist mechanisch wichtig: Die Index-Suche liefert bei einem Fehlschlag minus eins, und wer das nicht abfängt, greift mit einem ungültigen Index zu. Und der letzte ist die Zusammenfassung — ein geteiltes Array umzudrehen, bricht Programmteile, die davon nichts wissen.
Objekte als Datenstruktur
10:19 Zurück zu den Objekten, jetzt aus der Perspektive der Datenstruktur. Ein Punkt in diesem Kapitel erzeugt später erfahrungsgemäß die meisten Fehler — und es ist einer, den wir bereits kurz gestreift haben. Diesmal sehen wir ihn in Aktion. Ein Objekt passt, wenn Daten benannte Felder haben. Das ist der Fall bei einem einzelnen Datensatz, bei einer Konfiguration, bei der Antwort einer Schnittstelle.
10:43 Der Unterschied zum Array ist die Zugriffslogik: Dort greifen Sie über eine Position zu, hier über einen Namen — und Namen sind aussagekräftiger als Zahlen. Der zweite Satz weist auf die Realität hin: Objekte enthalten oft weitere Objekte. Eine Adresse in einem Kunden, ein Ansprechpartner in einem Beet. Diese Verschachtelung ist völlig normal — und sie ist der Grund, warum das Kopieren gleich komplizierter wird, als es aussieht.
11:09 Hier ist die angekündigte Falle, und ich empfehle Ihnen, dieses Beispiel selbst laufen zu lassen. Die Drei-Punkt-Schreibweise erzeugt eine Kopie — aber nur der obersten Ebene. Der Name wird tatsächlich kopiert und lässt sich unabhängig ändern. Das innere Objekt aber wird nicht kopiert; beide Objekte zeigen darauf. Ändern Sie also die Adresse in der vermeintlichen Kopie, ändern Sie sie auch im Original. Die Ausgabe belegt es.
11:35 Die Lösung steht in der letzten Zeile: Das innere Objekt muss ausdrücklich mitkopiert werden. Bei tieferer Verschachtelung wird das mühsam — dann greift man zu anderen Mitteln. Die Abgrenzung noch einmal auf den Punkt gebracht: Objekt, wenn die Felder Namen tragen und der Datensatz für sich steht. Array, wenn eine Reihenfolge gleichartiger Einträge gemeint ist.
11:56 Ein Verstoß dagegen fällt sofort auf — wer in einem Objekt Felder durchnummeriert, hat eigentlich eine Liste gebaut. Die beiden unteren Punkte greifen auf, was wir bei den nullish-Operatoren gelernt haben, jetzt im Kontext verschachtelter Daten: Die optionale Verkettung fängt fehlende Zwischenebenen ab, statt einen Fehler auszulösen.
12:15 Und zusammen mit dem Fallback-Operator entsteht daraus ein sicherer Zugriff mit Ersatzwert. Das ist ein Muster, das Sie täglich brauchen werden. Kopieren Sie ein verschachteltes Objekt so, dass eine Änderung an der inneren Ebene das Original nachweislich unberührt lässt. Und beachten Sie den Hinweis, der pädagogisch der wichtigste Teil ist: Prüfen Sie zuerst mit der flachen Kopie. Der Fehler muss einmal sichtbar gewesen sein.
12:40 Wer nur die richtige Lösung schreibt, merkt sich eine Regel. Wer den Fehler einmal produziert hat, merkt sich die Ursache — und erkennt sie später in fremdem Code wieder, auch wenn sie dort ganz anders aussieht. Die Drei-Punkt-Kopie für eine tiefe Kopie zu halten, führt die Liste an und ist der Fall aus dem Codebeispiel.
12:58 Der zweite Punkt ist die Kehrseite der optionalen Verkettung: Ohne sie löst der Zugriff auf eine fehlende Zwischenebene einen echten Fehler aus, der das Programm anhält. Punkt drei ist die Strukturfrage — durchnummerierte Felder in einem Objekt sind ein sicheres Zeichen dafür, dass eine Liste gemeint war. Und der letzte Punkt ist unser Dauerbrenner aus Modul drei, hier noch einmal in Erinnerung gerufen: Eine Zuweisung ist keine Kopie. Beide Namen zeigen auf dasselbe Objekt.
Map und Set
13:26 Jetzt zwei Strukturen, die viele Entwickler zu selten benutzen — oft, weil sie mit einem Objekt oder einem Array irgendwie auch hinkommen. Irgendwie ist hier aber deutlich schlechter als genau. Nachschlagen und Eindeutigkeit, das sind die beiden Themen. Eine Map ist ein Nachschlagewerk: Schlüssel-Wert-Paare, mit gezieltem Zugriff über den Schlüssel.
13:46 Ein entscheidender Vorteil gegenüber dem Objekt steht im Nebensatz — die Schlüssel dürfen jeden Typ haben. Bei einem Objekt sind sie immer Text; wer eine Zahl als Schlüssel nimmt, bekommt sie stillschweigend in Text umgewandelt. Ein Set wiederum ist eine Sammlung eindeutiger Werte: Was doppelt hineinkommt, wird nur einmal gespeichert, ohne dass Sie etwas dafür tun müssen.
14:07 Die Abgrenzung zum Objekt merken Sie sich am besten so: Der Datensatz ist ein Objekt, das Nachschlagewerk ist eine Map. Oben die drei Grundoperationen: eintragen, holen, prüfen ob vorhanden. Beachten Sie, dass hier Methoden aufgerufen werden statt der Punktschreibweise — eine Map ist kein Objekt, auch wenn sie ähnlich wirkt. Der untere Block ist der elegante Teil.
14:29 Beim Durchlaufen liefert jede Runde ein Paar aus Schlüssel und Wert, und mit der Array-Destrukturierung aus Modul drei lesen Sie beides direkt in zwei Variablen ein. Der Code liest sich dann fast wie ein Satz: für jede Kennung mit ihrem Beet. Diese Kombination aus Map und Destrukturierung ist ein sehr häufiges Muster in modernem JavaScript.
14:50 Die erste Ausgabe ist die Pointe: Drei Werte hineingegeben, zwei drin. Der doppelte Eintrag verschwindet automatisch, ohne Prüfung, ohne Schleife. Beachten Sie außerdem die Bezeichnung für die Größe — sie heißt anders als beim Array, und diese kleine Inkonsistenz erwischt jeden mindestens einmal. Der interessanteste Teil steht unten: Ein Set aus einem Array zu bauen, ist der schnellste Weg zu einer Liste ohne Dubletten.
15:13 Mit der Drei-Punkt-Schreibweise wandeln Sie es anschließend wieder in ein Array zurück. Diese zwei Zeilen ersetzen eine Schleife mit Prüfung, die man früher tatsächlich von Hand geschrieben hat. Zwei Teile, die zusammen die Abgrenzung dieses Kapitels üben. Erstens: Holen Sie ein Beet über seine Kennung — in konstanter Zugriffszeit, also ohne die Liste zu durchsuchen.
15:36 Das ist der Unterschied zwischen Nachschlagen und Suchen, und bei wachsenden Datenmengen wird er dramatisch. Zweitens: Erzeugen Sie eine Liste der vorkommenden Arten, in der jede Art genau einmal steht. Ein Hinweis, der Ihnen Sucherei erspart: Ein Set kennt keine Länge im Array-Sinn, seine Größe heißt anders. Die falsche Bezeichnung für die Größe eines Sets kostet Sie zwei Minuten und ist harmlos.
16:00 Eine Map mit Punktschreibweise anzusprechen, ist heimtückischer: Sie legen damit eine ganz normale Objekteigenschaft an, die mit dem Inhalt der Map nichts zu tun hat — und wundern sich, warum das Nachschlagen nichts findet. Der dritte Punkt knüpft an die Gleichheit aus Modul vier an: Bei Objekten in einem Set zählt die Referenz, nicht der Inhalt.
16:19 Zwei inhaltsgleiche Objekte sind für ein Set zwei verschiedene Werte. Und der letzte ist eine Angemessenheitsfrage — eine Map für einen einzelnen Datensatz ist Overkill.
Mengenoperationen
16:29 Zum Abschluss etwas, das lange in der Sprache gefehlt hat und inzwischen eingebaut ist: Vereinigung, Schnittmenge, Differenz. Das Beispiel, an dem wir es zeigen, macht deutlich, warum sich das im Code so angenehm liest. Mengenoperationen vergleichen zwei Sets miteinander. Manche liefern ein neues Set zurück, andere schlicht wahr oder falsch.
16:50 Und der wichtigste Zusatz steht am Ende: Die Ausgangsmengen werden dabei nicht verändert. Diese Methoden gehören also zu der Familie, die wir im dritten Kapitel gelobt haben — sie erzeugen Neues, statt Bestehendes umzubauen. Was hier passiert, ist im Grunde Mengenlehre aus der Schule, in Codeform. Und der Reiz liegt darin, dass fachliche Fragen sich oft genau so formulieren lassen: Ist alles Nötige vorhanden? Was fehlt? Was haben beide gemeinsam?
17:18 Sechs Operationen, und sie zerfallen in zwei Gruppen. Die ersten vier liefern eine neue Menge — alle Werte beider, nur die gemeinsamen, nur die der ersten, oder die, die genau in einer von beiden vorkommen. Die letzten beiden liefern nur wahr oder falsch: Steckt die eine Menge komplett in der anderen? Gibt es überhaupt keine Überschneidung?
17:38 Achten Sie auf den Fußtext, er ist ernst gemeint: Das sind neuere Sprachfeatures. Bevor Sie sie produktiv einsetzen, prüfen Sie die Zielumgebung — genau die Übung, die wir im ersten Modul gemacht haben. Berechtigungen sind das ideale Beispiel, weil sie tatsächlich Mengen sind: eine Menge vorhandener Rechte, eine Menge benötigter Rechte.
17:58 Und jetzt lesen Sie die dritte Zeile einmal laut: Ist die Menge der nötigen Rechte eine Teilmenge der vorhandenen? Genau so würde die fachliche Frage lauten. Ohne diese Methode bräuchten Sie eine Schleife mit einer Prüfung und einer Merkvariablen — funktional dasselbe, aber der Zusammenhang zur Fachfrage geht dabei verloren.
18:17 Die Differenz darunter beantwortet die Folgefrage, welche Rechte über das Nötige hinausgehen. Und ganz unten die Prüfung auf Überschneidungsfreiheit. Formulieren Sie die Prüfung, ob alle nötigen Rechte vorliegen — in einer Zeile, und für einen fehlenden Eintrag muss sie falsch liefern. Der eigentliche Auftrag steckt aber im Hinweis: Vergleichen Sie Ihre Lösung mit der Schleifenvariante und entscheiden Sie, welche näher an der Fachfrage steht.
18:42 Diese Art von Vergleich lohnt sich immer wieder. Code, der so klingt wie die fachliche Anforderung, lässt sich gegen die Anforderung prüfen. Code, der die Anforderung in eine Mechanik übersetzt, muss man erst zurückübersetzen — und dabei entstehen Missverständnisse. Bei der Differenz die Reihenfolge zu vertauschen, liefert präzise das Gegenteil dessen, was Sie wollten — und weil das Ergebnis plausibel aussieht, fällt es nicht sofort auf.
19:07 Ähnlich bei der Verwechslung von einfacher und symmetrischer Differenz: Die eine liefert, was nur in der ersten Menge steckt, die andere alles, was nicht in beiden steckt. Der dritte Punkt ist der Verfügbarkeitshinweis, den ich hier ausdrücklich wiederhole, weil es neue Features sind. Und der letzte ist mechanisch: Diese Methoden erwarten ein Set, kein Array. Ein Array übergeben führt zu einem Fehler, nicht zu einer stillen Umwandlung.
Die passende Struktur ist gewählt
19:31 Drei Sätze zum Mitnehmen. Erstens die Auswahlregel: Array für Reihenfolge, Objekt für benannte Felder, Map zum Nachschlagen, Set für Eindeutigkeit — vier Fragen, vier Antworten. Zweitens das Thema, das sich durch dieses ganze Modul zog: Die klassischen Methoden zum Anhängen, Entfernen, Sortieren und Umdrehen verändern das Original, ihre modernen Zwillinge mit dem to davor nicht.
19:53 Und drittens die Falle, die wir zweimal gesehen haben: Die Drei-Punkt-Schreibweise kopiert nur die oberste Ebene. Im nächsten Modul bringen wir diese Sammlungen in Fluss — es geht um Gruppieren, Iterieren und Datenfluss.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →