Hallo Rolf
Danke für das Beispiel zur Objektdestrukturierung. Dass das bei Parametern auch geht, hatte ich gar nicht auf dem Schirm.
Ja, das geht.
function handler({ target }) {
console.info(`event dispatched to ${ target.tagName }`)
}
Mittlerweile auch mit Restsyntax, wenn nur einige Objekteigenschaften an Bezeichner gebunden werden sollen, die anderen aber später noch gebraucht werden. Bei der folgenden Notation werden eigene, abzählbare Eigenschaften des übergebenen Objektes, die nicht zuvor an einen Bezeichner gebunden wurden, in ein planes Objekt kopiert, dass dann über den Namen des Restparameters referenziert werden kann. Gibt es keine weiteren Eigenschaften, dann wird ein leeres Objekt erzeugt.
function useRest({ property, ...others }) {
}
Wenn nicht sicher ist, dass ein Objekt an die Funktion übergeben wird, kann ein Defaultparameter angegeben werden, damit der Zugriff auf Objekteigenschaften nicht zu einem Typfehler führt. Hier gilt wie üblich, dass der als Standardwert notierte Ausdruck nur ausgewertet wird, wenn kein Argument übergeben wurde. Eigenschaften des als Ersatz angegebenen Objektes werden also nicht berücksichtigt, wenn ein übergebenes Objekt destrukturiert wird.
function playSafe({ property } = {}) {
}
Wenn Standardwerte für einzelne Eigenschaften angegeben werden sollen, ist die Syntax dieselbe wie für gewöhnliche Parameter. Auch die Auswertung erfolgt analog.
function hasDefault({ property = 'value' }) {
}
Soll eine Eigenschaft an einen anderen Bezeichner als den Eigenschaftsnamen gebunden werden, notiert man erst den Namen der Eigenschaft, einen Doppelpunkt und schließlich den Bezeichner, an den der Wert gebunden werden soll. Für den ursprünglichen Namen der Eigenschaft wird dann keine Bindung im lokalen Scope angelegt.
function changeName({ propertyName: parameterName }) {
}
Soll zusätzlich ein Standardwert definiert werden, wird die übliche Syntax verwendet. Die Zuweisung erfolgt dabei an den neuen Parameternamen, wird also hinter diesem notiert.
function changeNameWithDefault({ propertyName: parameterName = 'value' }) {
}
Die obige Syntax zur Umbenennung ist insbesondere dann von Belang, wenn es sich bei dem jeweiligen Eigenschaftsnamen nicht um einen validen Bezeichner handelt. Hier gelten ja unterschiedliche Regeln. Zum Beispiel können reservierte Wörter als Eigenschaftsnamen verwendet werden.
function handlesReservedWord({ for: _for }) {
}
Oder ein String, der unerlaubte Zeichen enthält, oder aber grundsätzlich erlaubte Zeichen an der falschen Stelle.
function handlesString({ '--custom-property': customProperty }) {
}
Es ist auf diese Weise auch möglich Symbole als Schlüssel zu verwenden. Ist etwa wie im folgenden Beispiel ein Symbol an einen Namen innerhalb der lexikalischen Umgebung der Funktion gebunden, kann auch dieses als Name der Eigenschaft verwendet werden, unter Verwendung der Syntax für berechnete Eigenschaftsnamen.
const key = Symbol()
function handlesSymbol({ [key]: parameterName }) {
}
Handelt es sich bei dem Wert einer Objekteigenschaft selbst um ein Objekt, dann kann auch dieses Objekt im selben Ausdruck destrukturiert werden. Die Syntax ist so ähnlich wie bei der Umbenennung: An Stelle des Parameternamens wird das Muster für die Destrukturierung angegeben. Für den Eigenschaftsnamen wird auch in diesem Fall keine Bindung im Scope der Funktion angelegt.
function useNestedObject({ object: { property } }) {
}
useNestedObject({
object: {
property: 'value'
}
})
Das kann auch zusammen mit einem Standardwert verwendet werden. In der Praxis wird man ja ohnehin eher den Fall haben, dass zwar grundsätzlich ein Objekt übergeben wird, aber einzelne Eigenschaften nicht vorhanden oder auf null
gesetzt sind.
function useNestedObjectWithDefault({ object: { property } = {} }) {
}
Wird ein Objekt als Argument an die Funktion übergeben, das eine Eigenschaft besitzt, deren Wert ein iterierbares Objekt ist, also etwa ein Array, dann kann man das auf dieselbe Art destrukturieren.
function useNestedIterable({ iterable: [head, ...tail] }) {
}
useNestedIterable({
iterable: [1, 2, 3, 4, 5]
})
Insgesamt ist zu beachten, dass wenn bei der Destrukturierung von Objekten ein Name angegeben wird, sowohl das Objekt selbst als auch die Kette seiner Prototypen danach durchsucht wird. Ganz so, wie beim normalen Zugriff auf Objekteigenschaften auch. Wird hingegen die Restsyntax verwendet, dann werden nur eigene Eigenschaften kopiert, deren Attribut enumerable
den Wert true
besitzt. Objekte als Eigenschaftswerte werden bei diesem Vorgang nicht geklont, sondern es wird nur die Referenz kopiert.
function invokesGetter({ property }) {
}
invokesGetter({
get property() {
return 'value'
}
})
Ist eine Eigenschaft als Getter implementiert, dann wird dieser bei der Destrukturierung aufgerufen und der Rückgabewert an den gewählten Bezeichner gebunden. Wird jedoch die Restsyntax verwendet, dann wird auf dem neuen Objekt eine gewöhnliche Dateneigenschaft angelegt und der zurückgegebene Wert im Attribut value
gespeichert. Der Wert wird also beim Zugriff auf das Restobjekt nicht mehr neu berechnet.
Viele Grüße,
Orlok
„Dance like it hurts.
Make love like you need money.
Work when people are watching.“ — Dogbert