Zum Inhalt springen
aviral gupta

// B5.3 · ca. 30 Min. · Einstieg

Objekte, Destrukturierung und Spread

Nach dieser Lektion bauen und ändern Sie Objekte, entpacken sie per Destrukturierung, kopieren und mischen sie mit Spread und lesen verschachtelte Werte sicher.

Lektion 3 von 5 in B5 Arrays, Objekte und JSON

Danach können Sie

  • Schlüssel eines Objekts lesen, hinzufügen, ändern und löschen, mit in und Object.hasOwn prüfen und mit Object.entries durchlaufen
  • Arrays und Objekte per Destrukturierung entpacken, mit Standardwerten und neuen Namen, auch in Funktionsparametern
  • Objekte mit Spread kopieren und mischen, wissen, dass die Kopie flach ist, und verschachtelte Werte mit ?. lesen
  1. Aufwärmen · Aufgabe 1 von 7

    Zum Aufwärmen: Was gibt dieser Code aus?

    const book = { title: "Dune", year: 1965 };
    console.log(book.title, book.pages);
  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es vorher, bevor Sie weiterlesen: Was gibt dieser Code aus?

    const a = { size: "M", colour: "red" };
    const b = { ...a, size: "L" };
    console.log(a.size, b.size, b.colour);
  3. Üben · Aufgabe 3 von 7

    Der zu lesende Schlüssel steht in der Variable key. Füllen Sie die Lücke so, dass die Zeile den Schlüssel liest, den key nennt, welcher es auch ist.

    const item = { price: 4, name: "tea" };
    const key = "price";
    console.log(item[____]);
    console.log(item[]);
  4. Üben · Aufgabe 4 von 7

    user ist { name: "Ada" } und list ist [5, 6, 7]. Ordnen Sie jeder Zeile zu, was sie anlegt.

  5. Üben · Aufgabe 5 von 7

    Was gibt dieser Code aus?

    const stock = { apples: 3, pears: 0 };
    console.log(Object.keys(stock), Object.values(stock));
  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Das Programm ändert nur die Kopie. Was gibt es aus?

    const original = { name: "Ada", address: { city: "Berlin" } };
    const copy = { ...original };
    copy.name = "Grace";
    copy.address.city = "Paris";
    console.log(original);
  7. Anwenden · Aufgabe 7 von 7

    Kleine Aufgabe: eine Kontaktkarte. Legen Sie ein Objekt mit Name, E-Mail und Telefonnummer an. Fügen Sie eine Stadt hinzu, ändern Sie die E-Mail und löschen Sie die Telefonnummer, und geben Sie dann jeden Schlüssel und Wert mit Object.entries und for...of aus. Destrukturieren Sie name und eine company mit dem Standardwert "none". Erstellen Sie mit Spread eine geänderte Kopie mit neuer Stadt und geben Sie beide Städte aus, um zu zeigen, dass das Original seine behalten hat. Lesen Sie zum Schluss mit ?. eine Straße aus einer fehlenden Adresse.

    Prüfen Sie Ihr Ergebnis anhand dieser Liste

Selbst programmieren

Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.

Ausgearbeitetes Beispiel

Ein Benutzerprofil

Ein Profilobjekt, auf alle Arten dieser Lektion verwendet: Es wird mit Punkt und mit Klammern gelesen, geändert, mit in und Object.hasOwn geprüft, mit Object.entries durchlaufen, mit Umbenennung und Standardwert entpackt und mit Spread gemischt. Der letzte Teil zeigt die flache Kopie: Der neue Name der Kopie bleibt in der Kopie, ihre neue Stadt erreicht aber das Original.

main.js

// A user profile: read, change, loop, unpack, copy and merge.
const user = { name: "Ada", city: "Berlin", tags: ["admin"] };
console.log(user.name, user["city"], user.age);

const key = "city";
user[key] = "Munich";
user.age = 36;
delete user.tags;
console.log(user);
console.log("age" in user, Object.hasOwn(user, "tags"));

for (const [k, v] of Object.entries(user)) {
  console.log(`${k} = ${v}`);
}

const { name, age: years, role = "guest" } = user;
console.log(name, years, role);

const defaults = { theme: "light", lang: "en" };
const settings = { ...defaults, lang: "de" };
console.log(settings, defaults);

const original = { name: "Ada", address: { city: "Berlin" } };
const copy = { ...original };
copy.name = "Grace";
copy.address.city = "Paris";
console.log(original);
console.log(original.phone?.mobile, original.address?.city);

Ausführen mit

node main.js

Ausgabe

Ada Berlin undefined
{ name: 'Ada', city: 'Munich', age: 36 }
true false
name = Ada
city = Munich
age = 36
Ada 36 guest
{ theme: 'light', lang: 'de' } { theme: 'light', lang: 'en' }
{ name: 'Ada', address: { city: 'Paris' } }
undefined Paris
  • user.age ist zuerst undefined, weil es den Schlüssel noch nicht gibt.
  • user[key] mit key = "city" ändert den Schlüssel city.
  • role hat keinen Schlüssel in user und bekommt deshalb den Standardwert "guest"; age wird in years umbenannt.
  • settings hat lang "de" vom späteren Schlüssel, und defaults bleibt unverändert.
  • original.address.city wurde über die Kopie zu Paris, weil address geteilt wird.
Ändern und ausführen

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Übungen

Übung 1 von 2

Ein Produkt und einen Benutzer sicher lesen

label(product) soll Name, Doppelpunkt, Preis und Währung zurückgeben, etwa Tea: 3 EUR. Hat das Produkt keine Währung, nehmen Sie EUR. cityOf(user) soll die Stadt des Benutzers zurückgeben, user.address.city, oder "unknown", wenn er keine Adresse hat. Der Starter gibt bei fehlender Währung undefined aus und stoppt bei fehlender Adresse mit einem TypeError. Beheben Sie beides: Destrukturierung mit Standardwert hilft beim ersten, ?. und ?? beim zweiten.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Führen Sie die Tests aus: Das Label endet auf undefined, weil das Produkt keinen Schlüssel currency hat.

  2. Hinweis 2

    Entpacken Sie den Parameter mit einem Standardwert: function label({ name, price, currency = "EUR" }).

  3. Hinweis 3

    user.address ist bei Bo undefined. user.address?.city ergibt undefined statt eines Fehlers, und ?? "unknown" ersetzt es.

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

// "Tea: 3 EUR"; the currency is EUR when the product has none.
export function label({ name, price, currency = "EUR" }) {
  return name + ": " + price + " " + currency;
}

// The user's city, or "unknown" when there is no address.
export function cityOf(user) {
  return user.address?.city ?? "unknown";
}
Auf dem eigenen Computer ausführen

Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.js

// "Tea: 3 EUR"; the currency is EUR when the product has none.
export function label(product) {
  return product.name + ": " + product.price + " " + product.currency;
}

// The user's city, or "unknown" when there is no address.
export function cityOf(user) {
  return user.address.city;
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {label, cityOf} from './main.js';

test('label verwendet die Währung des Produkts', () => {
  const got = label({ name: 'Tea', price: 3, currency: 'USD' });
  assert.equal(got, 'Tea: 3 USD', `label hat ${JSON.stringify(got)} zurückgegeben, erwartet "Tea: 3 USD"`);
});

test('label nimmt EUR, wenn das Produkt keine Währung hat', () => {
  const got = label({ name: 'Milk', price: 1.2 });
  assert.equal(got, 'Milk: 1.2 EUR', `label hat ${JSON.stringify(got)} zurückgegeben, erwartet "Milk: 1.2 EUR"`);
});

test('cityOf liest die Stadt aus der Adresse', () => {
  const got = cityOf({ name: 'Ada', address: { city: 'Berlin' } });
  assert.equal(got, 'Berlin', `cityOf hat ${JSON.stringify(got)} zurückgegeben, erwartet "Berlin"`);
});

test('cityOf ergibt unknown, wenn es keine Adresse gibt', () => {
  const got = cityOf({ name: 'Bo' });
  assert.equal(got, 'unknown', `cityOf hat ${JSON.stringify(got)} zurückgegeben, erwartet "unknown"`);
});

package.json

{
  "type": "module"
}

package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.

Programm ausführen:

node main.js

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

node --test
learnrun.js herunterladen

Übung 2 von 2

Die Kopie ändern, nicht das Original

withQuantity(item, quantity) soll ein neues Objekt mit allen Schlüsseln von item und der angegebenen quantity zurückgeben und item unverändert lassen. copyCart(cart) soll eine Kopie eines Warenkorbs { owner, items } zurückgeben, die neue Artikel bekommen kann, ohne den ursprünglichen Warenkorb zu ändern. Der Starter ändert item selbst, und seine Warenkorbkopie teilt sich das Array items. Beheben Sie beides mit Spread.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Führen Sie die Tests aus: Nach withQuantity(item, 5) hat der ursprüngliche Artikel die Menge 5. Die Zuweisung an item ändert das Objekt des Aufrufers.

  2. Hinweis 2

    Bauen Sie stattdessen ein neues Objekt: { ...item, quantity }. Der spätere Schlüssel gewinnt, und quantity ist die Kurzform von quantity: quantity.

  3. Hinweis 3

    { ...cart } ist flach: Die Kopie teilt sich cart.items. Geben Sie ihr ein eigenes Array: { ...cart, items: [...cart.items] }.

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

// A new object: item with this quantity. item stays unchanged.
export function withQuantity(item, quantity) {
  return { ...item, quantity };
}

// A copy of the cart whose items can change on their own.
export function copyCart(cart) {
  return { ...cart, items: [...cart.items] };
}
Auf dem eigenen Computer ausführen

Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.js

// A new object: item with this quantity. item stays unchanged.
export function withQuantity(item, quantity) {
  item.quantity = quantity;
  return item;
}

// A copy of the cart whose items can change on their own.
export function copyCart(cart) {
  return { ...cart };
}

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {withQuantity, copyCart} from './main.js';

test('withQuantity gibt den Artikel mit der neuen Menge zurück', () => {
  const got = withQuantity({ name: 'Tea', quantity: 1 }, 3);
  assert.deepEqual(got, { name: 'Tea', quantity: 3 }, `withQuantity hat ${JSON.stringify(got)} zurückgegeben, erwartet {"name":"Tea","quantity":3}`);
});

test('withQuantity lässt den ursprünglichen Artikel unverändert', () => {
  const item = { name: 'Tea', quantity: 1 };
  withQuantity(item, 5);
  assert.equal(item.quantity, 1, `die Menge des ursprünglichen Artikels wurde ${item.quantity}, erwartet war, dass sie 1 bleibt`);
});

test('copyCart kopiert owner und items', () => {
  const got = copyCart({ owner: 'Ada', items: ['tea'] });
  assert.deepEqual(got, { owner: 'Ada', items: ['tea'] }, `copyCart hat ${JSON.stringify(got)} zurückgegeben`);
});

test('Ein Artikel in der Kopie lässt den ursprünglichen Warenkorb in Ruhe', () => {
  const cart = { owner: 'Ada', items: ['tea'] };
  const copy = copyCart(cart);
  copy.items.push('milk');
  assert.deepEqual(cart.items, ['tea'], `die items des ursprünglichen Warenkorbs wurden zu ${JSON.stringify(cart.items)}, erwartet ["tea"]`);
});

package.json

{
  "type": "module"
}

package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.

Programm ausführen:

node main.js

Prüfungen ausführen (learnrun.js muss im selben Ordner liegen):

node --test
learnrun.js herunterladen

Häufige Fehler

for...of über ein Objekt

const prices = { tea: 3, milk: 1.2 };
for (const price of prices) {
  console.log(price);
}

Was Node.js ausgibt

TypeError: prices is not iterable

Warum, und die Lösung

for...of durchläuft Arrays und Strings, aber ein einfaches Objekt ist nicht iterierbar. Machen Sie zuerst ein Array daraus: Object.values(prices) für die Werte, Object.keys(prices) für die Namen oder Object.entries(prices) für beides: for (const [name, price] of Object.entries(prices)) { … }.

Einen Parameter destrukturieren, der nicht übergeben wurde

function greet({ name }) {
  return "Hello, " + name;
}
console.log(greet());

Was Node.js ausgibt

TypeError: Cannot destructure property 'name' of 'undefined' as it is undefined.

Warum, und die Lösung

greet entpackt sein erstes Argument, aber der Aufruf übergibt keines, also versucht es, name aus undefined zu lesen. Übergeben Sie ein Objekt, greet({ name: "Ada" }), oder geben Sie dem Parameter ein Standardobjekt: function greet({ name } = {}) { … }; name ist dann undefined statt eines Fehlers und kann einen eigenen Standardwert haben: { name = "friend" } = {}.

Durch einen fehlenden Schlüssel hindurch lesen

const user = { name: "Ada" };
console.log(user.address.city);

Was Node.js ausgibt

TypeError: Cannot read properties of undefined (reading 'city')

Warum, und die Lösung

user hat keine address, also ist user.address undefined, und city aus undefined zu lesen ist ein TypeError. Die Meldung nennt den Schlüssel, der gelesen werden sollte. Wenn ein Teil fehlen kann, nutzen Sie Optional Chaining: user.address?.city ergibt undefined. Mit ?? kommt ein Ersatzwert dazu: user.address?.city ?? "unknown".

JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode

Abschlussquiz

5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.

Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.

Problem melden

Etwas ist falsch oder unklar? Beschreiben Sie es kurz, dann wird es geprüft und korrigiert.

#

Mindestens 20 Zeichen.

Nur, wenn Sie eine Antwort wünschen.

Kernideen

Benannte Werte an einem Ort

Ein Objekt-Literal fasst Werte unter Schlüsseln zusammen: const user = { name: "Ada", city: "Berlin" };. Lesen Sie einen Schlüssel mit Punkt, user.name, oder mit eckigen Klammern und einem String, user["city"]; Klammern nehmen auch eine Variable, user[key]. Ein Schlüssel, den es nicht gibt, ergibt undefined, keinen Fehler. Eine Zuweisung fügt einen Schlüssel hinzu oder ändert ihn: user.age = 36. delete user.city entfernt einen. "age" in user und Object.hasOwn(user, "age") sagen, ob der Schlüssel da ist. Object.keys, Object.values und Object.entries liefern Arrays, also durchläuft for (const [k, v] of Object.entries(user)) ein Objekt; for...of auf dem Objekt selbst scheitert. Die Kurzform { name, age } bedeutet { name: name, age: age }.

Destrukturierung entpackt Werte

const { name, city } = user; legt zwei Konstanten aus den gleichnamigen Schlüsseln an. Mit einem Doppelpunkt benennen Sie um, { age: years }, mit = geben Sie einen Standardwert, { role = "guest" }: Er gilt, wenn der Schlüssel fehlt oder undefined ist. Arrays werden nach Position entpackt: const [first, second] = list;, und eine Lücke überspringt ein Element: const [, second] = list;. Destrukturierung funktioniert auch in Parametern: function label({ name, price }) { … } nimmt ein Objekt und entpackt es. Ganz ohne Argument aufgerufen, stoppt sie mit TypeError: Cannot destructure property 'name' of 'undefined'; ein Standardwert, ({ name } = {}), verhindert das.

Spread kopiert eine Ebene, ?. liest sicher

Spread kopiert die Schlüssel eines Objekts in ein neues: { ...defaults }. Zum Mischen verteilen Sie mehrere, und spätere Schlüssel gewinnen: { ...defaults, lang: "de" } behält jeden Standardwert außer lang. Die Kopie ist flach: Ein verschachteltes Objekt oder Array wird nicht kopiert, beide Objekte teilen es, also ändert copy.address.city = "Paris" auch original.address. Eine Zuweisung, const b = a;, kopiert gar nichts; a und b sind ein Objekt. Verschachtelte Teile kopieren Sie selbst, etwa { ...cart, items: [...cart.items] }. Optional Chaining hält bei undefined oder null an: user.address?.city ergibt undefined, wo user.address.city einen TypeError werfen würde.

Quellen

Zuletzt geprüft am 3. Oktober 2026