SELF-Treffen in Mannheim 2025

SELFHTML wird 30 Jahre alt! → Veranstaltungs-Ankündigung.

JavaScript/Destrukturierung

Aus SELFHTML-Wiki
< JavaScript(Weitergeleitet von Destrukturierung)
Wechseln zu: Navigation, Suche

Unter Destrukturierung versteht man in JavaScript eine besondere Syntax, mit der Werte von Objekteigenschaften oder Elemente eines iterierbaren Objektes an Variablen, Konstanten, Parameter von Funktionen oder Eigenschaften eines anderen Objektes gebunden werden können.

Allgemeine Beschreibung

Destrukturierungsausdrücke vereinfachen bestimmte, häufig wiederkehrende Abläufe bei der Arbeit mit zusammengesetzten Datentypen wie Objekten oder Arrays. Sie können überall dort verwendet werden, wo die JavaScript-Syntax das Binden eines Wertes an einen Namen zulässt: - in Variablendeklarationen - in Zuweisungsausdrücken (mit einer kleinen Besonderheit) - in Funktionsparametern - in for...in- oder for...of-Schleifen - in der catch-Klausel von try und catch

Sollen zum Beispiel einige Objekteigenschaften an Variablen zugewiesen werden, dann müsste man ohne Destrukturierung jeden Eigenschaftsname zweimal notieren – einmal als Name der Variable und einmal beim Zugriff auf die Eigenschaft.

Daten aus einem Objekt auslesen
// Ein beispielhaftes Objekt
const person = {
    vorname: 'Fritz',
    name: 'Müller',
    id: 4711
};

// Eigenschaften an Variablen zuweisen
const name = person.name
      id   = person.id;

Handelt es sich nur um eine einzelne Eigenschaft, deren Wert an eine Variable gebunden werden soll, dann ist der Bedarf an einer kürzeren Schreibweise nicht direkt ersichtlich. Sollen aber wie im Beispiel mehrere Eigenschaften eines Objektes übertragen werden, wird ein Destrukturierungsmuster nützlich:

Destrukturierung eines Objekts
const person = {
    vorname: 'Fritz',
    name: 'Müller',
    id: 4711
};

// Objekt-Destrukturierung
let { name, id } = person;
Beachten Sie: Die gezeigte Destrukturierung ist Teil der let-Deklaration, d.h. hier werden die Variablen name und id auch deklariert. Eine Variable kann in einem Scope nur einmal deklariert werden, d. h. wenn Sie im Anschluss ein anderes Objekt in die gleichen Variablen destrukturieren wollen, müssen Sie einen Zuweisungsausdruck benutzen. Bitte beachten Sie dazu den Folgeabschnitt über Destrukturierung im Zuweisungsoperator.


Destrukturierungsmuster eignen sich für Objekte und Arrays. Für Arrays – genauer gesagt: für iterierbare Objekte – sieht es so aus:

Destrukturierung eines Arrays
const primzahlen = [ 2, 3, 5, 7, 11 ];

// Array-Destrukturierung
const [ p1, p2 ] = primzahlen;
console.log(p1, p2);     // 2, 3
// Array-Destrukturierung mit Überspringen von Werten
const [ , , p3, , p4 ] = primzahlen;
console.log(p3, p4);     // 5, 11

Die einfachste Form einer Objektdestrukturierung besteht aus einem Paar geschweifter Klammern, innerhalb derer die Namen der Eigenschaften (durch Komma getrennt) notiert werden, die man in eine Variable übertragen möchte. Man muss dabei nicht jede Eigenschaft des Objekts ansprechen, eine Teilmenge ist ebenfalls möglich. Man kann auch Namen angeben, die im Objekt als Eigenschaft nicht existieren. Diesen wird undefined als Wert zugeordnet.

Eine einfache Arraydestrukturierung verwendet eckige Klammern und listet so viele Variablen auf, wie vom Beginn des Arrays an gelesen werden sollen. Sollen Werte im Array übersprungen werden, lässt man den Variablennamen einfach weg, wie in der zweiten Destrukturierung Arraybeispiels gezeigt wird

Beachten Sie: Die Destrukturierung ist eine reine Leseoperation. Das destrukturierte Objekt oder Array wird dabei nicht verändert.

Destrukturierung im Zuweisungsoperator

Im Zusammenhang mit dem Zuweisungsoperator sind einige Bemerkungen zur Destrukturierung angebracht.

Zuweisungsanweisung

Bei der Objektdestruktuierung in einem Zuweisungsanweisung ist zu beachten, dass diese Zuweisung zusätzlich in Klammern gesetzt werden muss. Ohne die Klammern wäre das Destrukturierungsmuster nicht von einem Anweisungsblock zu unterscheiden und JavaScript würde sich mit einem Syntaxfehler über das =-Zeichen beschweren.

Destrukturierung eines Objekts als Zuweisung
const person = {
    vorname: 'Fritz',
    name: 'Müller',
    id: 4711
};
let name, id;

// Zuweisung mit Objekt-Destrukturierung braucht Klammern!
({ name, id} = person);

Wert der Zuweisung

Bekanntlich ist das =, mit dem Zuweisungen durchgeführt werden, ein Operator und Operatoren haben ein Ergebnis. Bei der Erklärung des Operators haben wir geschrieben, dass der Wert der Zuweisung der zugewiesene Wert ist, das Ergebnis von a = { foo: 1, bar: 2} ist also das Objekt { foo: 1, bar: 2}.

Bei einer Destrukturierung wird möglicherweise mehr als ein Wert zugewiesen. Es stellt sich daher die berechtigte Frage, was das Ergebnis von ({ foo:a, bar:b} = { foo: 1, bar: 2}) ist!

Ergebniswert einer destrukturierenden Zuweisung
"use strict";
const objekt = { foo: 1, bar: 2 };

const a = ( { foo, bar } = objekt );

console.log(foo, bar);
console.log(a);

Bereit für ein Quiz?

Was steht in den Variablen (nicht Objekt-Eigenschaften!) foo und bar?
Antwort anzeigenDas war eine Trickfrage! Die Antwort ist: Gar nichts, denn weil wir den strict mode aktiviert haben, bricht das Programm wegen undeklarierter Variablen ab. Mit einem vorgeschalteten let foo, bar; geht es, und die Werte, die sie bekommen, sind wie erwartet: foo enthält objekt.foo, also 1, und bar enthält objekt.bar, also 2.
Sind die Klammern um die Destrukturierungszuweisung hier ebenfalls nötig?
Antwort anzeigenNein, sie können entfallen. Nötig sind sie nur, wenn die destrukturierende Zuweisung eine eigene Anweisung ist. Sie stehen hier lediglich der besseren Lesbarkeit halber.
Masterfrage: Was steht in a?
Antwort anzeigenDa es keine vernünftige Regel gibt, wie man das Destrukturierungsergebnis als Wert der Zuweisung definieren könnte, ist das Ergebnis der Zuweisung ganz banal das zugewiesene Objekt. Die zweite Konsolenausgabe zeigt also
►{foo: 1, bar: 2}

Objektdestrukturierung mit Umbenennen

Es ist nicht immer gewünscht, Objekteigenschaften in einer Variable mit dem Namen der Eigenschaft zu speichern. In den Beispielen im Einführungsabschnitt haben wir das gemacht. Aber – das ist nicht die einzige Möglichkeit.

Darüber hinaus ist es auch nicht immer möglich, Objekteigenschaften in eine gleichnamige Variable zu schreiben, weil Objekteigenschaften Namen haben können, die keine gültigen Variablennamen sind.

Sehen Sie das Objektdestrukturierungsmuster ähnlich wie ein Objektliteral. Das Literal besteht aus Eigenschaftsnamen und aus Werten, die diese Eigenschaften bekommen sollen. Ein Destrukturierungsmuster können Sie sich wie ein rückwärts angewendetes Literal vorstellen: dort, wo beim Literal die Eigenschaftswerte notiert werden, stehen im Destrukturierungsmuster die Namen der aufnehmenden Variablen.

Objektdestrukturierung mit Umbenennung
const person = {
    vorname: 'Fritz',
    name: 'Müller',
    id: 4711
};
const { vorname: kundeVorname, name: kundeNachname } = person;
console.log(kundeVorname, kundeNachname);     // Fritz Müller

Für den Fall, dass Sie ein Objekt mit Eigenschaftsbezeichnungen haben, die keine gültigen Variablennamen darstellen, müssen Sie den Eigenschaftsnamen in Anführungzeichen setzen oder sogar auf die Syntax für berechnete Eigenschaftsnamen zurückgreifen.

Objektdestrukturierung bei schwierigen Eigenschaftsnamen
const knifflig = {
         'class': 'of 1984',
         '123Eigenschaft': 'Wert für 123',
         [Symbol.species]: 'Tyrannosaurus Rex'
      };

const { 'class': _class, '123Eigenschaft': onetwothree, [Symbol.species]: spezies } = knifflig;

In der Variablen knifflig wird mit einem Objektliteral ein Objekt erzeugt, das drei Eigenschaften besitzt. Die erste Eigenschaft hat den Namen class, was ein reserviertes Wort in JavaScript ist und deshalb nicht als Name erlaubt ist. Die zweite Eigenschaft heißt 123Eigenschaft, dies ist kein gültiger JavaScript-Name. Die Anführungszeichen lösen beide Probleme.

Die dritte Eigenschaft wird mit Hilfe eines Symbols benannt, dem vordefinierten @@species-Symbol. Hier helfen auch keine Anführungszeichen mehr, dieses Symbol wird von JavaScript in der Eigenschaft species der Symbol-Konstruktorfunktion bereitgestellt, weshalb die Index-Syntax für berechnete Eigenschaftsnamen verwendet wird.

Das Destrukturierungsmuster verwendet nun genau die gleichen Schreibweisen. Die Namen class und 123Eigenschaft werden in Anführungszeichen gesetzt, und weil @@species sich nicht als Literal schreiben lässt, wird Symbol.species als variable Namensquelle herangezogen.

Beachten Sie: Wenn Sie die Syntax für variable Eigenschaftsnamen verwenden, muss die Umbenennungssyntax verwendet werden. Es wäre zwar denkbar, in den eckigen Klammern den Namen einer existierenden Variablen anzugeben, das würde die JavaScript-Engine aber dazu zwingen, zur Laufzeit eine Variablenbindung herzustellen.

Destrukturierung in vorhandene Arrays und Objekte

Genauso, wie man einem Arrayelement oder einer Objekteigenschaft einen Wert zuweisen kann, lässt sich ein Arrayelement oder eine Objekteigenschaft auch als Zuweisungsziel in einem Destrukturierungmuster verwenden.

Destrukturierung mit Zuweisung an eine Objekteigenschaft
const person = {
    vorname: 'Fritz',
    name: 'Müller',
    id: 4711
};
const kunde = { typ: 'Kunde' };
const liste = [];

({ vorname: kunde.vorname, name: kunde.nachname, id: liste[0] } = person;
console.log(kunde);     // { typ: 'Kunde', vorname: 'Fritz', name: 'Müller' }
console.log(liste);     // [ 4711 ]

Dieses Beispiel speichert person.vorname in kunde.vorname, person.name in kunde.nachname und person.id in liste[0]

Auf diese Weise kann man sogar Elemente in einem Array vertauschen, ohne temporäre Variablen deklarieren zu müssen. Aber Vorsicht, ein temporärer Parkplatz für die Daten muss trotzdem gebildet werden.

Ringtausch von Arrayelementen per Destrukturierung
const array = [ 1, 2, 3, 4, 5 ];

[ array[1], array[2], array[0] ] = [ array[0], array[1], array[2] ]
console.log(array);     // [ 3, 1, 2, 4, 5 ]

Vielleicht hätten Sie gedacht, dass man [ array[1], array[2], array[0] ] = array; hätte schreiben können. Leider nicht. Die Destrukturierung erfolgt von links nach rechts, und ohne das temporäre Array, das rechts vom Gleichheitszeichen erstellt wird, würde im ersten Schritt array[0] an array[1] zugewiesen und der zweite Schritt würde in array[1] schon den neuen Wert vorfinden. Das Ergebnis wäre [1, 1, 1, 4, 5].

Exotischere Beispiele

Es wird grundsätzlich zwischen zwei Destrukturierungsmustern unterschieden: Objektdestrukturierung mit geschweiften Klammern und Arraydestrukturierung mit eckigen Klammern.

Ein Arraydestrukturierungsmuster kann auf alle iterierbaren Objekte angewendet werden. Das sind natürlich alle Arrays, aber auch alle anderen Objekte, die einen Iterator anbieten, wie Map, NodeList oder eine selbst geschriebene Generatorfunktion. Die Zuweisung der beim Destrukturieren gefundenen Daten erfolgt an Hand ihrer Position im Arraydestrukturierungsmuster.

Beispiele für Arraydestrukturierungsmuster
// p1, p2, p3 erhalten Referenzen auf die ersten 3 p-Elemente im Dokument
const [p1, p2, p3] = document.querySelectorAll("p");

// Generatorfunktion, die 3 Zeichenketten liefert
function* gen123() {
   yield 'A';
   yield 'B';
   yield 'C';
}
// x und z erhalten das erste und dritte Generatorergebnis: 'A' und 'C'
const [x, , z] = gen123();

Ein Objektdestrukturierungsmuster kann auf alle Objekte angewendet werden, sogar auf Arrays! Hier erfolgt die Zuweisung der destrukturierten Werte basierend auf dem Namen im Objektdestrukturierungsmuster.

Beispiele für Objektdestrukturierungsmuster
const arr = [ 1, 2, 3, 4 ];

// Jedes Array hat eine length-Eigenschaft, diese wird in anzahl gespeichert
let { length: anzahl } = arr;

// Objektliterale erlauben numerische Schlüssel, Destrukturierungsmuster auch. Und weil Array-Indizes
// technisch nichts weiter als Objekteigenschaften sind, kann man ein Array auch als Objekt destrukturieren
// arr[3] wird in a gespeichert, arr[1] in b, arr[2] in c und arr[0] in d
let { 3: a, 1: b, 2: c, 0: d } = arr;

Wohin mit dem ...Rest?

Der Rest-Operator, den Sie vielleicht schon einmal bei Funktionsparametern gesehen haben, ist auch in Destrukturierungsmustern anwendbar. Wenn wir zum Beispiel ein Array in seine beiden ersten Elemente und die übrigen Elemente aufteilen möchten, lässt sich das so machen:

Die beiden ersten Elemente eines Arrays abtrennen
let werte = [1, 2, 3, 4, 5, 6];

// a und b vorher deklarieren. Das Destrukturierungsmuster soll das existierende "werte"-Array
// ersetzen, deshalb kann beim Destrukturieren nicht deklariert werden.
let a, b;

// Erstes Element nach a, zweites nach b, aus den übrigen wird ein neues Array gebildet 
// und nach "werte" zurückgeschrieben.
[a, b, ...werte] = werte;
console.log(a, b, werte);   // 1 2  ►(4) [3, 4, 5, 6]

// Erstes Element nach a, zweites überspringen, drittes nach b, die übrigen ins Rest-Array
[a, , b, ...werte] = werte;
console.log(a, b, werte);   // 1 3  ►(4) [4, 5, 6]
Beachten Sie: Bei der Arraydestrukturierung gehen übersprungene Werte verloren, sie gelangen nicht in die Rest-Variable!

Überlegen Sie vorher, ob es sinnvoll ist, so vorzugehen. Konstrukte dieser Art sind in funktionalen Programmiersprachen sehr beliebt, allerdings sind diese Sprachen auch auf solche Konstrukte hin optimiert. Will man in einem größeren Array per Schleife jeweils zwei Elemente verarbeiten und den Rest per „Überlaufarray” für den nächsten Durchlauf einsammeln, muss JavaScript viele temporäre Arrays erzeugen und wieder verwerfen.

Interessanterweise lässt sich der Rest-Operator auch in einer Objektdestrukturierung einsetzen. Bei einem Array nimmt die Variable am Rest-Operator die nicht „verbrauchten“ Arrayelemente auf, bei einem Objekt dementsprechend die nicht genutzten Objekteigenschaften. Allerdings nicht alle – geerbte Eigenschaften bleiben außen vor und Eigenschaften, die nicht als enumerable gekennzeichnet sind, ebenso.

Objekt aufteilen mit Destrukturierung und Rest-Operator
const auto = { marke: "Gauß", modell: "E", treibstoff: "Elektro", leistung: 190 };
let info = {}, sonstiges;

({ leistung: info.leistung, modell: info.modell, ...sonstiges } = auto);

console.log(info, sonstiges);
// ►{leistung: 190, modell: 'E'}  ►{marke: 'Gauß', treibstoff: 'Elektro'}

Wie schon gezeigt, kann ein Array auch als Objekt destrukturiert werden. Hier gibt es im Zusammenhang mit dem Rest-Operator einen interessanten Effekt. Während bei der Arraydestrukturierung übersprungene Elemente verschwinden, ist dass bei einer Objektdestrukturierung anders:

Array aufteilen mit Objektdestrukturierung und Rest-Operator
let werte = [1, 2, 3, 4, 5, 6];
let a, c;

( {0:a, 2:c, ...werte] = werte;
console.log(a, c, werte);
console.log(werte instanceof Array);
// 1 3 ►{1: 2, 3: 4, 4: 5, 5: 6}
// false

Man sieht, dass der übersprungene Arrayindex 1 im Rest enthalten ist. Das Ergebnis hat allerdings die Unschönheit, dass werte nun kein Array mehr ist, sondern ein einfaches Objekt. Und es gibt eine Merkwürdigkeit: jedes Array hat eine length-Eigenschaft, warum ist diese nicht im Rest-Objekt gelandet?

Erklärung anzeigenWenn Sie dem Link zur Beschreibung von length folgen, sehen Sie, dass diese Eigenschaft nicht enumerierbar ist. Der Restparameter der Objektdestrukturierung nimmt nur die enumerierbaren Eigenschaften auf.

Destrukturierung von Funktionsparametern

Funktionsparameter sind ein weiterer Ort, wo Werte an Namen gebunden werden. Und viele Funktionen erwarten ein oder mehrere Objekte als Argument, auf deren Eigenschaften sie dann zugreifen müssen. Andere erwarten vielleicht ein Array, bei dem sie auf einzelne Elemente zugreifen wollen. Auch hier ist Destrukturierung möglich. Nicht beim Funktionsaufruf, aber in der Parameterdeklaration der Funktion.

Destrukturieren von Funktionsargumenten
// Funktion zur Berechnung der Luminanz einer RGB-Farbe (ohne Gammakorrektur)
function getLuminance( {r, g, b} ) {
   return 0.2126*r + 0.7152*g + 0.0722*b;
}

const rgbColor = { r: 200, g: 75, b: 255 };
const luminanz = getLuminance(rgbColor);

Das Beispiel erhebt keinen Anspruch auf physiologische Korrektheit. Es definiert eine Funktion, die einer als Objekt repräsentierten RGB-Farbdarstellung einen Helligkeitswert zuordnet. In der Funktionsdeklaration wird eine Objektdekonstruktion verwendet, um aus dem übergebenen Objekt die r, g, und b Eigenschaften zu extrahieren und als eigene Parameter darzustellen.

Pfeilfunktionen

Destrukturierung der Parameter ist in einer Pfeilfunktion genauso gut möglich.

Destrukturierung in einer Pfeilfunktion
// Skalieren eines Punktes als Pfeilfunktion
const scale = ({x,y}, factor) => ({x: factor * x, y: factor * y});

// Ein Punkt als x/y-Objekt
const point = { x: 47, y: 99 };

console.log(scale(point, 10));
// Ausgabe:
// ► {x: 470, y: 900}

Der erste Parameter der scale-Funktion ist der Punkt, er wird destrukturiert entgegengenommen. Der Skalierungsfaktor ist ein normaler zweiter Parameter.

Die Rückgabe ist ein Objekt, das als Objektliteral notiert ist. Hier sind die runden Klammern wichtig, andernfalls würde JavaScript annehmen, dass die geschweiften Klammern einen Anweisungsblock bezeichnen sollen!

Fehler beim Destrukturieren

Wenn Sie eine Funktion mit Parameterdestrukturierung erstellen, dann müssen Sie darauf achten, dass die Funktion beim Aufruf auch etwas erhält, was sich wie gewünscht destrukturieren lässt.

Destrukturierungsfehler
function swap([a, b]) {
   return [b, a];
}

console.log( swap( ["ich","du"] ) );     // [ "du", "ich"]
console.log( swap("ich", "du") );        // [ "c", "i ]
console.log( swap(1, 2) );               // TypeError: number 1 is not iterable
console.log( swap() );                   // TypeError: undefined is not iterable

Das Beispiel zeigt eine Funktion, die ein Array erwartet und ein Array zurückgibt, das die beiden ersten Einträge im übergebenen Array in vertauschter Reihenfolge enthält. Vergisst man beim Aufruf, dass swap() ein Array erwartet, so können merkwürdige Dinge geschehen. Aufruf 1 erfolgt mit Arrayklammern und tut, was man erwartet. Im Aufruf 2 wird versucht, "ich" als Array zu destrukturieren, und das gelingt! Strings sind iterierbar, die Iteration liefert die in ihnen gespeicherten Zeichen. Deswegen ist das Ergebnis [ "c", "i" ]. Bei Aufruf 3 und 4 gibt es hingegen einen TypeError, weil weder die Zahl 1 noch der undefined-Wert, der nicht übergebenen Parametern zugewiesen wird, iterierbar sind.

Gegen solche Fehler können Sie nur bedingt Schutzmaßnahmen ergreifen. Ohne Destrukturierung hätten Sie die Möglichkeit, mit Array.isArray() den übergebenen Wert zu überprüfen, mit Destrukturierung bricht das Programm ab, bevor Sie etwas tun können.

Funktionen mit Defaultwerten

Funktionsparameter können Defaultwerte besitzen. Das ist bei Einsatz eines Destrukturierungs­musters ebenfalls möglich. Nehmen wir an, unsere getLuminance-Funktion soll für fehlende Farbkanäle den Wert 0 annehmen:

Destrukturieren von Funktionsargumenten mit Destrukturierungs­defaultwerten
function getLuminance( {r = 0, g = 0, b = 0} ) {
   return 0.2126*r + 0.7152*g + 0.0722*b;
}

Umbenennungen sind ebenfalls möglich, und sie lassen sich auch mit Destrukturierungs­defaultwerten kombinieren:

Destrukturieren von Funktionsargumenten mit Umbenennung und Destrukturierungs­defaultwerten
function getLuminance( {r:rot = 0, g:grün = 0, b:blau = 0} ) {
   return 0.2126*rot + 0.7152*grün + 0.0722*blau;
}

Parameterdefaultwert vs Destrukturierungs­defaultwert

Warum haben wir im vorigen Abschnitt das Begriffsmonstrum „Destrukturierungs­defaultwert“ ins Spiel gebracht? Weil es bei Funktionen tatsächlich zwei verschiedene Arten von Defaultwerten zu beachten gibt. Man hätte ja die getLuminance-Funktion auch auf diese Weise mit Defaultwerten ausstatten können:

Defaultwerte
function badLuminance_falsch( {r:rot, g:grün, b:blau} = { r: 0, g: 0, b: 0 } ) {
   return 0.2126*rot + 0.7152*grün + 0.0722*blau;
}
console.log(getLuminance( { r: 10, g: 20 } );         // Ausgabe: 16.43
console.log(getLuminance_falsch( { r: 10, g: 20 } );  // Ausgabe: NaN

Warum gibt die falsche Implementierung NaN aus? Wir haben hier keine Destrukturierungs­defaultwerte hinterlegt, sondern einen Parameter­defaultwert. Das heißt: dieser Defaultwert greift nur dann, wenn die Funktion überhaupt kein Argument übergeben bekommt. getLuminance_falsch() würde 0 liefern. Im Beispiel hingegen wird ein Objekt übergeben, in dem der Blauwert fehlt, und das Rechnen mit undefined führt zum Ergebnis NaN (Not A Number).

Destrukturierung in der for...of Schleife

Hinweis:
Syntaktisch ist die Destrukturierung zwar auch in der for...in-Schleife erlaubt, ergibt dort aber wenig Sinn, weil for...in lediglich eine Folge von Zeichenketten mit Eigenschaftsnamen liefert. Außer length sind hier keine Eigenschaften vorhanden.

Wenn die Elemente eines Arrays oder eines iterierbaren Objekts aus Objekten oder Arrays bestehen, kann es nützlich sein, die einzelnen Elemente in ihre Bestandteile zu zerlegen. Bei einem Map-Objekt ist es beispielsweise so, dass man in einer for...of-Schleife pro Durchlauf ein Array aus 2 Elementen erhält, nämlich den Schlüssel und den zugehörigen Wert. Das entspricht der Rückgabe der entries-Methode.

Es bietet sich an, dieses Array zu destrukturieren:

Destrukturieren einer Map-Iteration
const selfChairs = new Map();
selfChairs.set("Münz", "Stefan");
selfChairs.set("Rautenberg", "Sven");
selfChairs.set("Apsel", "Matthias");
selfChairs.set("Scharwies", "Matthias");

// Ohne Destrukturierung
for (const chairman of selfChairs) {
   console.log("%s %s", chairman[0], chairman[1]);
}

// Mit Destrukturierung
for (const [vorname, nachname] of selfChairs) {
   console.log("%s %s", vorname, nachname);
}

Wenn Sie nicht wissen, was die %s Angaben bei console.log bedeuten, schauen Sie bitte im console.log-Artikel nach.

Ebenso lassen sich Objekte im Schleifendurchlauf destrukturieren. Wir wollen eine Liste aller Links im Dokument ausgeben, mit ID, Linkziel und Linktext. Das NodeList-Objekt, das querySelectorAll zurückliefert, ist iterierbar und kann mit for...of durchlaufen werden:

Destrukturieren einer NodeList
for (const { id, href, textContent } of document.querSelectorAll("a")) {
   console.log("ID='%s', Ziel='%s', Text='%s'", id, href, textContent);
}

Destrukturierung von verschachtelten Objekten

Objekte sind häufig nicht einfache Schlüssel-Wert-Listen. Statt dessen verweisen ihre Eigenschaften wiederum auf andere Objekte oder enthalten Arrays. Ebenso kann ein Array statt einfacher Werte Objekte enthalten. Diese Schachtelung lässt sich durch Schachteln von Destrukturierungsmustern nachverfolgen. Das Prinzip ist dabei: Überall dort, wo ein Variable einen Wert zugewiesen bekommen kann, lässt sich eine Destrukturierung verwenden, um diesen Wert auf mehrere Variablen zu verteilen.

Objekt mit Array-Eigenschaft
const wurf = { spieler: 'Rolf', würfel: [4,11,17] };    /* Rolf würfelt mit einem W20! */

const { spieler, würfel:[ würfel1, ...rest] } = wurf;
console.log("Spieler %s hat als erstes die %d gewürfelt", spieler, würfel1);

Vergleichen Sie die Destrukturierung von wurf mit einer Umbenennung in der Destrukturierung. Beim einfachen Umbenennen hätte man

 const { spieler, würfel:liste } = wurf;

geschrieben und dann auf liste[0] zugreifen können. Heißt also: Hier wurde der Variablen liste ein Wert zugewiesen, und das wurde durch die Arraydestrukturierung [ würfel1, ...rest] erweitert.

Das geht auch andersherum:

Array mit Objekten
const mitspieler = [
   {name: 'Rolf', punkte: 17 },
   {name: 'Matthias', punkte: 19},
   {name: 'Felix', punkte:22 }
];

const [{punkte:maxPunkte}] = mitspieler.toSorted(
                               ({punkte:p1},{punkte:p2}) => p2 - p1
                             );

Die Methode toSorted erzeugt eine sortierte Kopie des Arrays, auf dem sie aufgerufen wird. Dazu benötigt sie eine Callback-Funktion, die die Arrayelemente vergleicht. Hierfür haben wir eine Pfeilfunktion eingesetzt, und weil wir gerade so schön beim Destrukturieren sind, haben wir aus den Mitspieler-Objekten, die dort als Argumente ankommen, auch gleich per Parameter­destrukturierung die Punktwerte herausgeholt. Diese müssen natürlich unterschiedliche Namen bekommen, deshalb kommt noch die Umbenennungs-Syntax zum Einsatz. Die Differenzbildung sorgt dafür, dass das Ergebnis eine nach Punkten absteigend sortierte Mitspielerliste ist.

Aus dieser wird mittels Arraydestrukturierung das erste Element herausgeholt, und in dieser Arraydestrukturierung erfolgt eine weitere Destrukturierung, die die Punktezahl des führenden Spielers extrahiert.