JavaScript/Destrukturierung
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.
ToDo (weitere ToDos)
Inhaltsverzeichnis
- 1 Allgemeine Beschreibung
- 2 Objektdestrukturierung
- 2.1 Zuweisungsausdrücke für Variablen und Konstanten
- 2.2 Zuweisungsausdrücke für Funktionsparameter
- 2.3 Verwendung von berechneten Eigenschaftsnamen
- 2.4 Bestimmung eines anderen Bezeichners an Stelle des Eigenschaftsnamens
- 2.5 Destrukturierung von mehreren verschachtelten Objekten
- 2.6 Angabe von Standardwerten für einzelne Objekteigenschaften
Allgemeine Beschreibung
Destrukturierungsausdrücke vereinfachen bestimmte, häufig wiederkehrende Abläufe bei der Arbeit mit zusammengesetzten Datentypen wie Objekten oder Arrays. Soll zum Beispiel der Wert einer Objekteigenschaft an eine Variable gebunden werden, um die wiederholte Referenzierung des Objektes zu vermeiden, dann würde ohne Destrukturierung der Eigenschaftsname zweimal notiert werden – einmal als Bezeichner der Variable und einmal beim Zugriff auf die Eigenschaft.
// Define ordinary object
let object = {
property: 'value'
};
// Assign to variable using member expression
let property = object.property;
Handelt es sich wie in dem Beispiel oben 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 jedoch mehrere Eigenschaften eines Objektes gelesen und ihr Wert in Variablen hinterlegt werden, dann entsteht bald der Wunsch nach einer kompakteren Schreibweise.
// Define ordinary object
let object = {
property: 'value'
};
// Assign to variable using object assignment pattern
let {property} = object;
Die Syntax für die Destrukturierung von Objekten löst dieses Problem. Wie in dem Beispiel oben zu sehen ist, wird hierbei auf der rechten Seite des Zuweisungsausdrucks nur eine Referenz auf das Objekt notiert. Auf der linken Seite werden – von geschweiften Klammern eingeschlossen – die Namen der Objekteigenschaften notiert, deren Wert an Variablen gebunden werden soll. Die wiederholte Referenzierung des Objektes und die doppelte Angabe des Eigenschaftsnamens entfällt.
// Object assignment pattern
const {name, age} = {name: 'Jane', age: 25};
// Array assignment pattern
const [head] = [1, 2, 3];
Es wird grundsätzlich zwischen zwei Destrukturierungsmustern unterschieden. Bei der Destrukturierung von gewöhnlichen Objekten wird direkt auf bestimmte Eigenschaften des destrukturierten Objektes zugegriffen und ihr Wert an einen Bezeichner gebunden. Bei der Destrukturierung von iterierbaren Objekten, wie zum Beispiel von Arrays, wird hingegen über das Objekt iteriert und die Elemente werden in der Reihenfolge an die angegebenen Bezeichner gebunden, in der sie ausgegeben wurden.
// Apply object assignment pattern to an iterable object
const {length} = [1, 2, 3];
Das verwendete Muster für die Destrukturierung wird allerdings nicht durch den Typ des destrukturierten Objektes vorgegeben. So ist zum Beispiel ein Array ein iterierbares Objekt, aber wie in dem Beispiel oben zu sehen ist, kann trotzdem mittels Objektdestrukturierung auf Eigenschaften des Arrays zugegriffen werden.
Objektdestrukturierung
Objekte zur Kapselung von Daten sind in JavaScript allgegenwärtig. Das liegt zum einen daran, dass es lange Zeit keine echten Alternativen zur Verwendung von Objekten gab. Zum anderen liegt es daran, dass die Sprache eine sehr elegante Syntax für die Definition von Objekten bereitstellt. Die Literalschreibweise für ein Objekt besteht aus nicht mehr als einem Paar geschweifter Klammern, das eine Liste von Eigenschaftsdefinitionen umschließt.
// Object initializer syntax
const Earth = {
type: 'Planet',
satellites: true,
color: 'blue'
};
// Reference properties with member expressions
let type = Earth.type, color = Earth.color;
Möchte man hingegen auf mehrere Eigenschaften eines bereits definierten Objekts zugreifen, so ist dies mit ungleich mehr Aufwand verbunden. Es muss für jede Eigenschaft das Objekt referenziert und der Eigenschaftsname angegeben werden, zusätzlich zu dem Bezeichner, an den der Wert der Eigenschaft gebunden werden soll, auch dann, wenn wie in dem Beispiel oben Bezeichner und Eigenschaftsnamen identisch sind. Das ist unnötig umständlich und begünstigt Fehler, weshalb diese Art des Zugriffs keine befriedigende Lösung darstellt.
Information
with
können Eigenschaften und Methoden eines Objekts direkt über ihren Namen angesprochen werden. Solche Anweisungen sind jedoch aus mehreren Gründen problematisch und sollten daher prinzipiell vermieden werden.
Die Objektdestrukturierung stellt eine elegante Alternative für den Zugriff auf Objekteigenschaften dar, die syntaktisch der Objektdefinition in Literalschreibweise ähnelt. Es werden an geeigneter Stelle einfach geschweifte Klammern notiert und darin eine Liste von Eigenschaftsnamen. Je nach Kontext werden die Werte der auf diese Weise referenzierten Eigenschaften dann in Variablen, Konstanten oder Parametern von Funktionen hinterlegt.
// Object initializer syntax
const Mars = {
type: 'Planet',
satellites: true,
color: 'red'
};
// Assign to variables using object assignment pattern
let {type, color} = Mars;
Anders als in dem ersten Beispiel oben, wird hier das zuvor in Literalschreibweise definierte Objekt bei der Variablendeklaration destrukturiert. Sowohl in diesem als auch im letzten Beispiel werden die Werte der beiden referenzierten Objekteigenschaften in gleichnamigen Variablen gespeichert, aber die Variante bei der das Objekt destrukturiert wird ist deutlich kürzer, wodurch die Lesbarkeit verbessert wird.
Zuweisungsausdrücke für Variablen und Konstanten
Bei der Objektdestrukturierung zum Zwecke der Zuweisung von Eigenschaftswerten an Variablen oder Konstanten sind im Wesentlichen zwei Fälle zu unterscheiden. Der erste Fall betrifft die Zuweisung bei der Deklaration der Variablen oder Konstanten. Hier wird zunächst wie üblich das Schlüsselwort let
oder const
notiert und danach der Destrukturierungsausdruck, gefolgt von einem Gleichzeichen und einem Ausdruck, dessen Wert eine Referenz auf das Objekt ist, das destrukturiert werden soll.
// Object definition
const border = {
color: 'green',
style: 'dashed',
width: 'thin'
};
// Declaration of a constant using object destructuring
const {color, width} = border;
// Variable declaration using object destructuring
let {style} = border;
Der zweite Fall betrifft die Zuweisung von Eigenschaftswerten an Variablen, die bereits deklariert wurden. Hier ist die Syntax im Prinzip dieselbe wie bei der Deklaration, jedoch ohne das Schlüsselwort let
. Anders als bei Variablen die mit var
deklariert werden, führt hier eine erneute Deklaration im selben Scope zu einem Syntaxfehler der dazu führt, dass das Programm nicht ausgeführt wird.
// Object definition
const animation = {
name: 'epileptic-seizure',
duration: 0.1,
iterationCount: 1000,
direction: 'alternate',
playState: 'paused'
};
// Declare variables without assignment
let name, playState;
// Assign to variables using object assignment pattern
({name, playState} = animation);
Ein weiterer Unterschied ist, dass in diesem Fall der gesamte Zuweisungsausdruck in runde Klammern gefasst werden muss. Der Grund dafür ist, dass die geschweiften Klammern sonst als Anweisungsblock interpretiert würden. Ein solcher kann auch abseits von Funktionen und Kontrollstrukturen für sich alleine stehen. Das nachfolgende Gleichheitszeichen würde dementsprechend einen Syntaxfehler produzieren.
Anders als in vielen vergleichbaren Programmiersprachen, ist die Notation eines Semikolons am Ende einer Anweisung in JavaScript nicht zwingend vorgeschrieben. Ein solches wird bei Bedarf automatisch eingefügt. Werden Anweisungen nicht explizit mit einem Semikolon beendet, dann ist es möglich, dass die runden Klammern um den Zuweisungsausdruck als Funktionsaufruf interpretiert werden. Dies gilt es also zu beachten.
Zuweisungsausdrücke für Funktionsparameter
Destrukturierungsausdrücke können nicht nur im Zusammenhang mit der Zuweisung von Eigenschaftswerten an Variablen oder Konstanten verwendet werden. Es können auch Objekte destrukturiert werden, die einer Funktion als Argument übergeben werden. Dabei wird der Destrukturierungsausdruck an der Stelle des Parameters der Funktion notiert, an der ein Objekt erwartet wird.
// Ordinary function definition
function handler({type, target}) {
// Print information about the event
console.log(`Event ${type} has been dispatched to ${target.tagName}.`);
}
In dem Beispiel oben wird ein Eventhandler definiert, der als Argument ein Objekt mit Informationen über das eingetretene Ereignis erwartet. Da hier lediglich der Inhalt der Eigenschaften type
und target
des Eventobjektes von interesse ist, wird statt eines normalen Parameternamens ein Destrukturierungsausdruck angegeben. Dabei wird innerhalb der runden Klammern für die Parameterliste ein Paar geschweifte Klammern notiert und darin die Namen der beiden Eigenschaften, deren Wert innerhalb der Funktion verwendet werden soll.
// Arrow function definition
const scale = ({value}, factor) => ({value: factor * value});
Ein Ausdruck zur Objektdestrukturierung kann – wie in dem Beispiel oben zu sehen ist – auch zusammen mit gewöhnlichen Parametern notiert werden. Der Ausdruck nimmt einfach eine Stelle in der Parameterliste ein. Wird wie oben eine Pfeilfunktion definiert, dann ist allerdings zu beachten, dass bei der Destrukturierung eines Objekts zwingend runde Klammern um die Liste der Parameter notiert werden müssen, selbst dann, wenn nur ein Argument erwartet wird, wobei die Klammern normalerweise weggelassen werden könnten.
Wird wie in dem letzten Beispiel von einer Pfeilfunktion ein Objekt zurückgegeben, dann müssen auch um das Objektliteral herum runde Klammern notiert werden, da die geschweiften Klammern sonst als Anweisungsblock interpretiert werden, der den Körper der Funktion umschließt. Der Doppelpunkt würde in diesem Fall zu einem Syntaxfehler führen.
Benötigt eine Funktion mehr als zwei oder drei Parameter, dann ist es regelmäßig eine gute Idee, statt einzelner Werte ein Objekt zu übergeben, in dem die Werte hinterlegt sind. Dadurch spielt es keine Rolle mehr, in welcher Reihenfolge die Argumente beim Funktionsaufruf notiert werden müssen, was den Code weniger fehleranfällig macht. Darüber hinaus wird durch die Benennung der übergebenen Werte die Lesbarkeit des Codes verbessert. Mittels Destrukturierung kann dann auf die Werte genauso einfach zugegriffen werden wie auf gewöhnliche Parameter.
Angabe eines Standardwertes
Soll die Übergabe eines Objekts an eine Funktion optional sein, dann muss für den entsprechenden Parameter der Funktion ein Objekt als Standardwert angegeben werden, wenn das als Argument übergebene Objekt direkt in der Parameterliste destrukturiert werden soll. Wird kein Standardwert angegeben, dann führt der Aufruf ohne Argumente zu einem Typfehler, da Parameter für die kein Argument übergeben wurde mit dem primitiven Wert undefined
initialisiert werden, der nicht implizit in ein Objekt konvertiert wird.
// Define function with default parameter
function maybeAssign(object, {value} = {}) {
// Parameter is undefined if no object is provided
if (value) {
object.property = value;
}
return object;
}
Auch wenn ein in der Parameterliste einer Funktion ein Destrukturierungsausdruck notiert wird, ändert sich an der Syntax für die Definition eines Defaultparameters nichts. Der Ausdruck tritt wie oben zu sehen ist einfach an die Stelle des Parameternamens. Dahinter wird wie üblich ein Gleichheitszeichen und der Ausdruck notiert, dessen Wert beim Fehlen eines Arguments eingesetzt werden soll, in dem Beispiel oben einfach ein leeres Objekt.
Information
Der hinter dem Gleichheitszeichen notierte Ausdruck wird nur ausgewertet, wenn das Argument für die Position des Parameters den Wert undefined
hat. Das bedeutet, dass Eigenschaften eines als Standardwert notierten Objektes nicht als Ersatz für fehlende Eigenschaften eines übergebenen Objektes dienen können. Soll für eine Eigenschaft ein Standardwert angegeben werden, dann muss dies innerhalb des Destrukturierungsausdrucks erfolgen.
Verwendung von berechneten Eigenschaftsnamen
Bei der Definition einer Objekteigenschaft muss der Name der Eigenschaft nicht zwingend als Literal notiert werden, unabhängig davon, auf welche Weise die Definition erfolgt. Wird eine Eigenschaft in einem Objektliteral definiert, dann kann an Stelle des Namens der Eigenschaft ein Paar eckige Klammern notiert werden und darin ein beliebiger Ausdruck, der zum Eigenschaftsnamen aufgelöst wird. Analog dazu kann auch bei der Destrukturierung ein berechneter Eigenschaftsname verwendet werden.
// Object destructuring with computed property name
function when(condition, {[condition ? 'whenTrue' : 'whenFalse']: value}) {
return value;
}
// Call function and store value
const value = when(true, {whenTrue: 1, whenFalse: 0});
In dem Beispiel oben wird eine Funktion definiert, die als zweiten Parameter ein Objekt erwartet, das direkt in der Parameterliste destrukturiert wird. Dabei wird der Name der Objekteigenschaft auf die zugegriffen werden soll – abhängig vom Wert des ersten Parameters – dynamisch berechnet und der Eigenschaftswert an den Bezeichner value
gebunden, der nach dem Ausdruck zur Berechnung des Namens und einem Doppelpunkt notiert wird.
// Object destructuring with computed property name
function unless({condition, [condition ? 'whenFalse' : 'whenTrue']: value}) {
return value;
}
// Call function and store value
const value = unless({condition: false, whenTrue: 1, whenFalse: 0});
Anders als im ersten Beispiel könnte der Parameter condition
für die Bedingung im ternären Ausdruck zur Berechnung der zu referenzierenden Objekteigenschaft auch selbst als Eigenschaft notiert werden, so wie in diesem Beispiel. Zu beachten ist aber, dass nur auf solche Bezeichner zugegriffen werden kann, für die zum Zeitpunkt des Zugriffs bereits eine Bindung im lokalen Scope existiert. Dabei spiel es keine Rolle, ob es sich um einen formalen Parameter oder um eine Eigenschaft eines oder desselben als Argument übergebenen Objektes handelt.
Bestimmung eines anderen Bezeichners an Stelle des Eigenschaftsnamens
Es ist möglich, bei der Destrukturierung eines Objektes für eine Eigenschaft einen anderen Bezeichner zu bestimmen als den Namen dieser Eigenschaft. Das kann erforderlich sein, weil der Eigenschaftsname kein gültiger Bezeichner ist, oder weil es im jeweiligen Scope bereits eine Bindung für den Namen der Eigenschaft gibt.
// Use a different identifier for the property
let {propertyName: variableName} = {propertyName: 'value'};
Die Syntax für die Umbenennung entspricht weitestgehend der Syntax bei der Verwendung von berechneten Eigenschaftsnamen. Das heißt, es wird zunächst der Name der Objekteigenschaft notiert, dann ein Doppelpunkt und schließlich der Bezeichner, an den der Wert der Eigenschaft gebunden werden soll. Für den Namen der Eigenschaft wird bei dieser Notation grundsätzlich keine Bindung angelegt.
Eigenschaftsname enthält unerlaubte Zeichen
Ein Grund dafür, dass bei der Destrukturierung eines Objekts ein anderer Bezeichner für eine Eigenschaft gewählt werden muss ist, dass der Eigenschaftsname für Bezeichner unerlaubte Zeichen enthält, oder aber grundsätzlich erlaubte Zeichen an der falschen Stelle, etwa Ziffern am Anfang des Wortes.
// Assign to valid identifier
let {'--custom-property': customProperty} = {'--custom-property': 'value'};
Wird ein Eigenschaftsname in Anführungszeichen notiert, kann eine beliebige Zeichenkette als Name verwendet werden. Handelt es sich bei dem Namen wie in dem Beispiel oben nicht um einen validen Bezeichner, wird eine Umbenennung vorgenommen, indem zunächst der ungültige Eigenschaftsname in Anführungszeichen und danach der Bezeichner notiert wird, an den der Eigenschaftswert gebunden werden soll.
Eigenschaftsname ist reserviertes Wort
Sowohl bei der Definition von Objekten in Literalschreibweise als auch beim Zugriff auf Objekteigenschaften über Elementausdrücke können reservierte Wörter ohne Anführungszeichen als Eigenschaftsname verwendet werden. Als Bezeichner für Variablen, symbolische Konstanten oder Parameter von Funktionen sind sie aber entweder grunsätzlich oder zumindest in bestimmten Kontexten ungültig.
// Defuse property name that is reserverd word
let {for: _for} = {for: 'you'};
So wie in einem Objektliteral, kann ein reserviertes Wort auch innerhalb eines Destrukturierungsausdrucks ohne Anführungszeichen notiert werden. Häufig wird bei der Wahl eines alternativen Bezeichners für ein reserviertes Wort einfach ein Unterstrich vorangestellt, so wie in dem Beispiel oben.
Eigenschaftsname ist Symbol
Als Name für eine Objekteigenschaft können nicht nur Werte vom Datentyp String eingesetzt werden, sondern auch Symbole. Die Syntax für berechnete Eigenschaftsnamen macht es möglich, bei der Destrukturierung eines Objekts auch solche Eigenschaften zu referenzieren. Hier ist zu unterscheiden zwischen Symbolen die nur lokal sichtbar sind und Symbolen, die im globalen Symbolregister hinterlegt sind.
// Store local symbol in constant
const propertyName = Symbol();
// Define object using the symbol as property name
const object = {
[propertyName]: 'value'
};
// Store value using object destructuring
let {[propertyName]: variableName} = object;
// Print value
console.log(variableName); // value
Handelt es sich so wie in dem Beispiel oben um eine Eigenschaft, deren Name ein lokal sichtbares Symbol ist, dann genügt es innerhalb von eckigen Klammern eine Referenz auf das Symbol zu notieren, sowohl bei der Definition der Eigenschaft als auch bei der späteren Referenzierung innerhalb des Destrukturierungsausdrucks. Wird das jeweilige Symbol so wie oben durch den Aufruf der Funktion Symbol
erzeugt, dann muss eine Referenz auf das Symbol sichtbar sein, damit die zugehörige Eigenschaft referenziert werden kann. Auf diese Weise erzeugte Symbole werden nämlich nicht im globalen Symbolregister gespeichert.
// Create object with global symbol as property name
function global() {
return {
[Symbol.for('peace')]: 'dove'
};
}
// Destructure object using global symbol
const {[Symbol.for('peace')]: symbol} = global();
// Print value
console.log(symbol); // dove
In diesem Beispiel ist aus Sicht der Anweisung, die den Destrukturierungsausdruck enthält, kein Bezeichner sichtbar an den ein Symbol gebunden wäre. Das Symbol, das bei der Erzeugung des Objekts durch die Funktion als Eigenschaftsname verwendet wurde, ist jedoch im globalen Symbolregister verzeichnet, da hier die Methode for
des Symbolobjektes verwendet wurde. Durch den erneuten Aufruf dieser Methode kann eine Referenz auf das Symbol geholt und als Eigenschaftsname bei der Destrukturierung eingesetzt werden.
Information
Object.getOwnPropertySymbols
können auch solche Objekteigenschaften referenziert werden, deren Name ein Symbol ist, das weder lokal sichtbar noch im globalen Symbolregister hinterlegt ist. Die Methode gibt für ein als Argument übergebenes Objekt ein Array mit Symbolen zurück, die Eigenschaftsnamen dieses Objekts sind. Diese können dann für den Zugriff auf die entsprechenden Eigenschaften genutzt werden.
Destrukturierung von mehreren verschachtelten Objekten
Objekte sind hervorragend dazu geeignet, hierarchische Zusammenhänge zu modellieren. Strukturen wie Graphen oder Bäume können auf Objekte abgebildet werden, die als Eigenschaften wiederum Referenzen auf andere Objekte besitzen. Ein Objekt muss also nicht zwingend eine flache Liste von Eigenschaften darstellen, sondern kann gegebenenfalls andere Objekte enthalten. Solche verschachtelten Objekte können ebenfalls in ein und demselben Ausdruck destrukturiert werden. Dabei können auch verschiedene Destrukturierungsmuster gemischt werden.
Eigenschaft ist gewöhnliches Objekt
Soll innerhalb eines Destrukturierungsausdrucks auf die Eigenschaften eines Objekts zugegriffen werden, das der Wert einer Eigenschaft des destrukturierten Objekts ist, dann wird zu diesem Zweck zuerst der Name der entsprechenden Eigenschaft notiert, gefolgt von einem Doppelpunkt und schließlich dem Muster für die Destrukturierung des verschachtelten Objekts.
// Define nested object
const outer = {
inner: {
property: 'value'
}
};
// Assign property of nested object
const {
inner: {
property
}
} = outer;
// Print value
console.log(property);
Zum besseren Verständnis ist in dem abstrakten Beispiel oben der Destrukturierungsausdruck der Schachtelung der Objekte gemäß formatiert, statt ihn wie üblich in einer Zeile zu notieren. So ist viel besser zu erkennen, dass der Ausdruck genau die Struktur der Objekte widerspiegelt. Es wird bloß keine Eigenschaft definiert, sondern nur über den Namen auf die Eigenschaft zugegriffen und ihr Wert in einer gleichnamigen Konstante hinterlegt.
// Define custom event
const earthquake = new CustomEvent('earthquake', {
bubbles: true,
detail: {
scale: 9.5,
type: 'megathrust'
}
});
// Store reference to object
const city = document.getElementById('Valdivia');
// Define event handler destructuring the nested event object
city.addEventListener('earthquake', function({detail: {type, scale}}) {
console.log(type, scale);
});
// Dispatch event to target
city.dispatchEvent(earthquake);
In diesem Beispiel wird ein mit CustomEvent
ein eigenes Ereignis definiert, das in der Folge auf einem bestimmten Element ausgelöst wird. Zuvor wird ein Eventhandler definiert, der beim Eintritt des Ereignisses aufgerufen wird. Der als Eventhandler registrierten Funktion wird bei ihrem Aufruf das Eventobjekt übergeben, dessen Eigenschaft detail
wiederum ein Objekt enthält. Auch dieses Objekt wird destrukturiert und der Wert der Eigenschaften in die Konsole geschrieben.
Eigenschaft ist iterierbares Objekt
Ist der Wert einer Eigenschaft eines destrukturierten Objekts ein iterierbares Objekt, wie beispielsweise ein Array, ein Set oder eine Map, dann können die Einträge dieses Objekts ebenfalls über ein Destrukturierungsmuster referenziert werden. Das Muster wird einfach hinter dem entsprechenden Eigenschaftsnamen notiert.
// Define object with array property
const object = {
array: [1, 2, 4, 8]
};
// Mixed object and array assignment pattern
let {array: [head, ...tail]} = object;
In dem Beispiel oben wird zunächst ein gewöhnliches Objekt definiert, dessen einzige eigene Eigenschaft eine Referenz auf ein Array enthält. Im nächsten Schritt wird das Objekt destrukturiert und auf die Eigenschaft array
zugegriffen. Statt eine Bindung für die Eigenschaft zu erzeugen, wird unter Verwendung der Syntax für die Destrukturierung von iterierbaren Objekten das erste Element des Arrays in einer Variable mit dem Namen head
hinterlegt. Die anderen Elemente des Arrays werden mittels Rest-Syntax aufgesammelt und an den Namen tail
gebunden.
Gemäß dem Fall, es handelt sich bei dem Wert einer Objekteigenschaft um ein Array, dessen Elemente selbst wieder Objekte sind, können auch diese Objekte wieder destrukturiert werden, indem an der gewünschten Position in der Liste ein entsprechender Destrukturierungsausdruck notiert wird.
Angabe von Standardwerten für einzelne Objekteigenschaften
Nicht immer ist sicher, dass eine Eigenschaft auf dem Objekt, das destrukturiert werden soll, auch definiert ist. Soll in einem solchen Fall ein Standardwert verwendet werden, kann dieser direkt bei der Destrukturierung angegeben werden. Die Syntax entspricht dabei der Notation von Standardwerten für Parameter, das heißt, es wird erst der Name der Objekteigenschaft angegeben, dann ein Gleichheitszeichen und schließlich der Standardwert.
// Object definition
const work = {
title: 'Hackers',
director: 'Iain Softley',
year: 1995
};
// Object assignment pattern with default value
let {title, category = 'film'} = work;
In diesem Beispiel wird ein gewöhnliches Objekt destrukturiert und dabei auf zwei Eigenschaften zugegriffen. Das referenzierte Objekt besitzt jedoch keine Eigenschaft mit dem Namen category
, was normalerweise dazu führen würde, dass als Ersatz der primitive Wert undefined
an den angegebenen Bezeichner gebunden wird. Da hier jedoch ein Standardwert bereitgestellt wurde, wird stattdessen der hinter dem Eigenschaftsnamen notierte String in einer Variable hinterlegt.
Berechnete Eigenschaftsnamen
Ein Standardwert kann auch in Verbindung mit berechneten Eigenschaftsnamen verwendet werden. Auch in diesem Fall wird der Zuweisungsausdruck – also das Gleichheitszeichen und der Ausdruck, dessen Wert als Ersatz für eine undefinierte Eigenschaft des destrukturierten Objekts dient – hinter dem Bezeichner notiert, an den der Wert gebunden werden soll.
// Object definition
const film = {
title: 'Tron',
director: 'Steven Lisberger',
year: 1982
};
// Computed property name with default value
let {title, ['DIRECTOR'.toLowerCase()]: director = 'unknown'} = film;
Wahl eines anderen Bezeichners
So wie bei der Verwendung von Standardwerten in Verbindung mit berechneten Eigenschaftsnamen wird auch verfahren, wenn der Eigenschaftswert an einen anderen Bezeichner als den Eigenschaftsnamen gebunden werden soll. Hier wird zunächst der Name der Eigenschaft notiert, dann ein Doppelpunkt, der neue Name und dann die übliche Syntax für den Standardwert.
// Object definition
const film = {
title: 'The Matrix',
directors: 'Lana and Lilly Wachowski',
with: [
'Keanu Reeves',
'Laurence Fishburne',
'Carrie-Anne Moss'
],
year: 1999
};
// Default value assignment with different identifier
let {title, with: starring = []} = film;
Dabei spielt es keine Rolle, ob der Name der Objekteigenschaft grundsätzlich ein valider Bezeichner ist oder nicht, ob die Umbenennung also erforderlich ist oder nur dem Wunsch des Programmierers entspricht. Der Ausdruck für den Standardwert wird prinzipiell nach dem Bezeichner notiert, der letztlich das Ziel der Zuweisung sein soll, so wie in dem Beispiel oben.
Verschachtelte Objekte
// Object definition
const film = {
title: 'WarGames',
details: {
director: 'John Badham',
year: 1983
}
};
// Default value assignment with nested object
let {title, details: {year = 'unknown'} = {}} = film;