Quiz: Destrukturierungsfreude
Bist du ein Destrukturierungs‑Meister?
Oder ist es deine Symphonie der Zerstörung?
Dieses Quiz prüft dein Wissen über Destructuring in JavaScript: von der „einfachen“ Objektsyntax über verschachteltes Destructuring bis hin zu Default‑Werten. Zusätzlich gibt es Bonusfragen zu TypeScript und Inline‑Typen!
Leg gleich mit dem Aufwärmen los – zeig, dass du Destructuring beherrschst! 👇
Was wird dieser Code ausgeben?
const person = { name: 'Dan Levy', location: 'Cape Town',};const { name, age } = person;console.log(`Name: ${name}, Age: ${age}`);Die Eigenschaft age existiert nicht auf person, also wird age undefined sein. Auf keinen Fall Infinity 😅
Das Ergebnis ist:
Name: Dan Levy, Age: undefinedWas macht dieser Code?
const person = [ 'Dan Levy', 'Cape Town' ];const [ name, origin, age ] = person;console.log(`Name: ${name}, Age: ${age}`);Die Variable age ist im tuple‑Array nicht vorhanden, also wird sie undefined sein.
Das führt zu:
Name: Dan Levy, Age: undefinedWie wäre es mit etwas verschachteltem Destructuring?
'use strict';const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first }, address: { city }, birth: { place },} = person;console.log( `First: ${first}, City: ${place}`,);Die Eigenschaft birth: { place } existiert nicht auf person, daher wird ein Fehler ausgelöst.
Eine Lösung ist, Standardwerte für verschachtelte Eigenschaften anzugeben.
Beim Zugriff auf verschachtelte Eigenschaften – sei vorsichtig – da die Fehler schwer zu erkennen sein können. Und Fehlermeldungen variieren zwischen Browsern und anderen Plattformen, was das Debuggen etwas schwieriger macht.
In modernem Chrome: TypeError: Cannot read properties of undefined (reading 'place')
In Node ist dies ebenfalls ein TypeError, weil JavaScript versucht, place aus undefined zu destrukturieren, bevor place überhaupt gelesen wird.
Der genaue Wortlaut variiert zwischen Browsern und Laufzeiten.
Jetzt mit ein paar Standardwerten, was passiert?
'use strict';const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first = 'Unknown' }, birth: { place = 'Unknown' },} = person;console.log( `Hi ${first} from ${place}`,);Die birth‑Eigenschaft existiert nicht auf person, also benötigt das gesamte Objekt immer noch einen Standardwert, nicht nur die verschachtelte Eigenschaft. Im Grunde fehlt hier ein = {}‑Standard.
So wie das geschrieben ist, bedeutet es: “wenn person.birth undefined ist, dann ist place Unknown”. Aber person.birth ist undefined, also versucht man, undefined zu destrukturieren, was zu einem Fehler führt.
In modern Chrome: `TypeError: Cannot read properties of undefined (reading 'place')`
In Node, this is also a `TypeError` because JavaScript tries to destructure `place` from `undefined`.
Exact wording varies between browsers and runtimes.Was wird das tun?
const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first = 'Unknown' }, birth: { place = 'Unknown' } = {},} = person;
console.log( `Hi ${first} from ${place}`,);Die Eigenschaft birth existiert nicht auf person, also wird auf ein leeres Objekt = {} zurückgegriffen. Dadurch kann der Standardwert verwendet werden.
Was macht das jetzt als Funktionsparameter?
'use strict';function displayUser({ name = "Unknown", age = -1,} = { place: "Unknown" }) { console.log(`Hi ${name} from ${place}`);}displayUser({ name: "Dan" });Diese Funktion extrahiert die Eigenschaften name und age und verwendet bei Bedarf Standardwerte. In diesem Fall ist der Schlüssel place im Default‑Objekt nur Rauschen, er wird in displayUser() nicht verwendet.
Der Strict‑Modus ändert daran nichts: Das Auslesen der nicht deklarierten Bindung place wirft einen ReferenceError.
Wie werden undefined‑Werte behandelt?
'use strict';function displayPlace({ name = "N/A", place = "N/A", age = -1,} = { place: "Unknown" }) { console.log(`${place}`);}displayPlace({ name: "Dan" });displayPlace({ name: "Dan", place: undefined });displayPlace({ name: "Dan", place: "Joburg" });Die Funktion displayPlace verwendet NUR ein Standard‑Objekt, wenn kein Objekt übergeben wird. Das heißt, das einzige, was das Standard‑Objekt { place: "Unknown" } liefert, ist ein Aufruf ohne Argumente displayPlace().
Ein weiteres bemerkenswertes Verhalten ist, dass das Übergeben von undefined für place dazu führt, dass der Standardwert verwendet wird – ein bisschen ähnlich wie bei JSON.stringify (ignoriert undefined, erkennt null).
Das Ergebnis ist:
displayPlace() // UnknowndisplayPlace({ name: "Dan" }) // N/AdisplayPlace({ name: "Dan", place: undefined }) // N/AÄhnlich wie beim Vorherigen… Wie wird null behandelt?_
function displayPlace({ name = "N/A", place = "N/A", age = -1,} = { place: "Unknown" }) { console.log(`${place}`);}displayPlace({ name: "Dan", place: null });displayPlace({ name: "Dan", place: undefined });In diesem Fall wird die Eigenschaft place beim ersten Aufruf auf null gesetzt und beim zweiten auf undefined. Der Standardwert für place wird nur verwendet, wenn das gesamte Objekt fehlt oder undefined ist. Null‑Werte bleiben null.
Jetzt in TypeScript… Was wird das tun?
'use strict';function displayPlace( { name = 'N/A', place = 'N/A', }: { name: string; place: string; age: number; },) { console.log(`${place}`);}displayPlace({ name: 'Dan', place: null });TypeScript meldet einen Fehler, weil place als string typisiert ist, aber der Aufruf null übergibt. Der Aufruf lässt außerdem die erforderliche Eigenschaft age weg.
Wenn du Typfehler ignorierst, wird beim Ausführen des Codes null in die Konsole ausgegeben.
Versuchen wir mal etwas Umbenennen/Zuweisung…
'use strict';function displayPlace({ name = 'N/A', place: location = 'N/A',}: { name: string; place: string; age?: number;}) { console.log(`${location}`);}displayPlace({ name: 'Dan', place: 'Denver' });Dies gibt Denver in der Konsole aus. Die Eigenschaft place wird in der Funktionssignatur zu location umbenannt. Das ist ein gängiges Muster (Eigenschaften beim Destrukturieren umbenennen), wenn man Datenstrukturen von Drittanbietern anpasst.
Finde den Typfehler:
function greet({ name: {first = "N/A", last = "N/A"}, birth: {place = "N/A"} = {}, age = -1,}: { name: {first?: string, last?: string}; birth: {place?: string}; age: number;}) { console.log(`Hi ${first} ${last} from ${place}`);}greet({ name: {first: 'Dan'} });Der Fehler liegt in der Signatur der greet‑Funktion. Die Eigenschaften age und birth fehlen im übergebenen Objekt, also sollten sie im Typdefinition optional sein.
Auch wenn die Eigenschaft birth mit einem Standardwert destrukturiert wird, verlangt die Typdefinition, dass sie vorhanden ist. Um eine Eigenschaft in TypeScript optional zu machen, sollte man den ?‑Operator verwenden.
Hinweis: birth?: { place?: string } ist nicht dasselbe wie birth: { place?: string } | undefined.
Jetzt mit Zuweisung (beachte die Variablen f, l und p)
'use strict';function greet( { name: {first: f = "N/A", last: l = "N/A"}, birth: {place: p = "N/A"} = {}, age = -1, }: { name: {first?: string, last?: string}; birth?: {place?: string}; age?: number; }) { console.log(`Hi ${f} ${l} from ${place}`); // What will 👆 do?}greet({ name: {first: 'Dan', last: 'Levy'}, birth: {place: 'Cape Town'},});Ein weiterer Fehler! Du fängst an zu raten, oder?!
Es ist schwer, mehrere Ebenen von Destrukturierung mit Defaults, Zuweisungen und Typen zu lesen!
Sobald place der Variable p zugewiesen wird, ist sie im Scope der console.log‑Anweisung nicht mehr definiert.
console.log(`Hi ${f} ${l} from ${place}`); // ❌// to:console.log(`Hi ${f} ${l} from ${p}`); // ✅