Daten modellieren: Objekte und JSON in JavaScript

Lerne, reale Daten mit JavaScript-Objekten zu modellieren: Erstelle und ändere Eigenschaften, durchlaufe sie und erkenne, warum das Kopieren einer Variablen nicht das Objekt kopiert, auf das sie verweist. Gib Objekten mit Methoden ein Verhalten und finde heraus, worauf sich das Schlüsselwort this bei den verschiedenen Aufrufarten bezieht. Entpacke und kombiniere Daten mit Destrukturierung, Spread und Rest, speichere Sammlungen in Map und Set und wandle Daten mit JSON.stringify und JSON.parse in JSON-Text und JSON-Text in Daten um.

AnfängerEinheit 4 von 9 in Kurs: JavaScript – DOM, Ereignisse und asynchroner Code

Was du lernst

  1. Beschreibe reale Dinge im Code als Objekte mit benannten Eigenschaften, lies und ändere diese Eigenschaften und verstehe, wie Objekte gespeichert, kopiert und verglichen werden.
    • Erstelle Objekte und arbeite mit ihren Eigenschaften
      Schreibe Objektliterale, lies Eigenschaften mit Punkt- und Klammernotation und füge Eigenschaften hinzu, ändere und lösche sie.
    • Prüfe und durchlaufe die Eigenschaften eines Objekts
      Prüfe, ob eine Eigenschaft existiert, liste Schlüssel, Werte und Schlüssel-Wert-Paare auf und durchlaufe oder transformiere die Eigenschaften eines Objekts.
    • Verstehe Referenzen, Kopieren und Vergleichen
      Erkläre, warum Objekte über Referenzen gemeinsam genutzt werden, vergleiche Objekte richtig und erstelle flache und tiefe Kopien.
    • Arbeite mit verschachtelten Daten
      Lies und verarbeite Objekte innerhalb von Objekten und Arrays aus Objekten, fange fehlende Teile mit ?. und ?? ab und wähle eine Struktur, die zu den Daten passt.
  2. Schreibe Methoden, die auf die Daten ihres Objekts zugreifen, erkläre, wie der Wert des Schlüsselworts this bei den verschiedenen Aufrufarten bestimmt wird, und behalte den richtigen Wert von this bei, wenn eine Methode weitergegeben wird.
    • Schreibe Methoden, die auf die Daten ihres Objekts zugreifen
      Definiere Methoden mit der Kurzschreibweise, lies und aktualisiere das Objekt mit this und rufe Methoden richtig auf.
    • Erkläre, wie der Wert von this bestimmt wird
      Bestimme den Wert von this anhand der Art, wie eine Funktion aufgerufen wird, und erkläre, warum sich Pfeilfunktionen anders verhalten.
    • Behalte den Wert von this bei, wenn du Methoden als Callbacks übergibst
      Erkenne, wann eine Methode ihr Objekt verliert, und behebe das mit einem Pfeilfunktions-Wrapper, bind, call oder apply.
  3. Hole Werte mit Destrukturierung aus Objekten und Arrays und kopiere, kombiniere und sammle Werte mit der Spread- und Rest-Syntax.
    • Destrukturiere Objekte
      Entpacke Objekteigenschaften in Variablen, mit Umbenennung, Standardwerten, verschachtelten Mustern und destrukturierten Funktionsparametern.
    • Destrukturiere Arrays und andere iterierbare Objekte
      Entpacke Werte anhand ihrer Position, überspringe sie oder lege Standardwerte fest, vertausche Variablen und destrukturiere Schlüssel-Wert-Paare in Schleifen.
    • Kopiere, führe zusammen und sammle mit Spread und Rest
      Kopiere und kombiniere Objekte und Arrays mit Spread und übergib Arrayelemente als Argumente, sammle Werte mit Rest und unterscheide die beiden.
  4. Verwende Map für Schlüssel-Wert-Sammlungen mit Schlüsseln beliebigen Typs und Set für Sammlungen eindeutiger Werte und wähle zwischen ihnen und einfachen Objekten und Arrays.
    • Speichere Schlüssel-Wert-Paare in einer Map
      Erstelle und aktualisiere eine Map, durchlaufe ihre Einträge, wandle Maps in Objekte und Objekte in Maps um und entscheide, wann eine Map besser passt als ein Objekt.
    • Speichere eindeutige Werte in einem Set
      Erstelle und aktualisiere ein Set, entferne Duplikate aus Arrays und vergleiche Sammlungen mit Mengenoperationen.
  5. Lies und schreibe das JSON-Textformat, wandle JavaScript-Werte mit JSON.stringify in JSON und JSON-Text mit JSON.parse zurück in Werte um und behandle die Fälle, in denen beides nicht übereinstimmt.
    • Lies und schreibe Daten im JSON-Format
      Erkenne gültiges JSON, erkläre, wie es sich von einem JavaScript-Objektliteral unterscheidet, und finde häufige Syntaxfehler.
    • Wandle Werte mit JSON.stringify in JSON-Text um
      Wandle Objekte und Arrays in JSON-Zeichenketten um, formatiere die Ausgabe, wähle die aufzunehmenden Eigenschaften und sage voraus, was weggelassen oder geändert wird.
    • Wandle JSON-Text mit JSON.parse in Werte um
      Parse JSON sicher, stelle Werte wie Datumsangaben mit einer Reviver-Funktion wieder her, prüfe die geparsten Daten und führe einen Roundtrip von Daten durch JSON aus.

Objekte und JSON in JavaScript einfach erklärt

5 Kapitel

1

Modelliere Daten mit Objekten

Ein Objekt hält zusammengehörige Werte unter Namen zusammen, sodass ein Datensatz ein Buch, eine Person oder eine Messung beschreiben kann. Mithilfe dieser Namen kannst du ein Feld ändern, einen ganzen Datensatz untersuchen und Listen von Datensätzen organisieren. Außerdem verfolgst du, welche Variablen auf dasselbe Objekt verweisen. Dieser Unterschied ist wichtig, wenn eine Änderung an zwei Stellen erscheint, eine Kopie verschachtelte Daten enthält oder ein fehlendes Feld einen sinnvollen Standardwert benötigt.

1.1 Erstelle Objekte und arbeite mit ihren Eigenschaften

Ein Objekt fasst zusammengehörige Werte unter Namen zusammen. Jede Eigenschaft ordnet einem Schlüssel einen Wert zu. Verwende ein Objekt für einen Datensatz und ein Array aus Objekten für eine geordnete Liste. Parallele Arrays können ihre Zuordnung verlieren, wenn nur eines sortiert oder geändert wird.

Einen Datensatz erstellen und lesen
const book = { title: "Dune", pages: 412, available: true };
book.title;    // "Dune"
book["title"]; // "Dune"

Eigenschaftswerte können neben primitiven Werten auch Arrays, Objekte oder Funktionen sein. Schlüssel sind Zeichenketten oder Symbole; diese Beispiele verwenden Zeichenketten. Zeichenkettenschlüssel, die gültige Bezeichner sind, brauchen keine Anführungszeichen. Schlüssel mit Leerzeichen oder Bindestrichen brauchen Anführungszeichen: { "release-year": 1965 }. Numerische Schlüssel werden zu Zeichenketten, daher hat { 1: "a" } den Schlüssel "1". Objektliterale erlauben ein abschließendes Komma.

Der Zugriff mit Punkt verwendet den wörtlichen Namen nach dem Punkt. Der Zugriff mit eckigen Klammern wertet einen Ausdruck aus:

const field = "pages";
book[field]; // 412
book.field;  // undefined

Der zweite Ausdruck sucht nach einer Eigenschaft namens "field". Eckige Klammern ermöglichen auch book["release-year"]. Eine fehlende Eigenschaft liefert undefined; ein weiterer Zugriff darauf, wie in book.author.name, löst einen TypeError aus, wenn author fehlt.

Den Inhalt des Objekts ändern
book.author = "Frank Herbert";
book.pages = 896;
delete book.available;

Eine Zuweisung fügt eine fehlende Eigenschaft hinzu oder ersetzt einen vorhandenen Wert. Das Löschen entfernt die Eigenschaft selbst, sodass "available" in book nun falsch ist. const hält die Variable an dieses Objekt gebunden, erlaubt aber Änderungen an dessen Inhalt.

Für const reading = { city: "Nairobi", tempC: 24.5 }; speichert reading.tempC += 1.5; den Wert 26. Dann fügt reading.humidity = 61; ein Feld hinzu. Mit const key = "humidity"; liest reading[key] den Wert 61. Ein Name wie tempC macht die Einheit der Messung sichtbar.

Variablen in einem Literal verwenden
const name = "Lena";
const age = 29;
const person = { name, age };
const lang = "nl";
const greeting = { [lang]: "Hallo" };

Die Kurzschreibweise { name, age } bedeutet { name: name, age: age }. Ein berechneter Name wertet den Ausdruck innerhalb der eckigen Klammern aus: greeting hat die Eigenschaft "nl". Ohne diese Klammern würde { lang: "Hallo" } den wörtlichen Schlüssel "lang" erstellen.

Wichtige Erkenntnisse

  • Ein Objekt fasst zusammengehörige Werte in benannten Eigenschaften zusammen.
  • Verwende eckige Klammern für einen in einer Variablen gespeicherten Schlüssel oder einen Schlüssel mit Bindestrich.
  • Eine Zuweisung fügt eine Eigenschaft hinzu oder ersetzt sie; delete entfernt sie.
  • const legt die Variable fest, nicht den Inhalt des Objekts.
  • Die Kurzschreibweise übernimmt einen Variablenwert; ein berechneter Schlüssel wertet einen Ausdruck aus.

1.2 Prüfe und durchlaufe die Eigenschaften eines Objekts

Zu prüfen, ob ein Feld existiert, ist etwas anderes, als seinen Wert zu prüfen. Eine leere Zeichenkette, null oder false kann ein durchaus gültiger gespeicherter Wert sein.

Die richtige Frage nach der Existenz stellen
const item = { stock: 0, note: undefined };
Object.hasOwn(item, "stock"); // true
"note" in item;                // true
Boolean(item.stock);          // false

Object.hasOwn(obj, key) prüft nur die eigenen Eigenschaften des Objekts. Der Operator in prüft auch geerbte Eigenschaften: "toString" in {} ist true, während Object.hasOwn({}, "toString") gleich false ist. Älterer Code ruft häufig obj.hasOwnProperty(key) auf.

Eine Bedingung wie if (item.stock) prüft, ob der Wert truthy ist. Sie kann ein fehlendes Feld nicht von einem vorhandenen Feld mit dem Wert null unterscheiden. Dasselbe Problem gilt für "", false, null, undefined und NaN. Selbst der Wert undefined kann zu einer vorhandenen Eigenschaft gehören, wie oben bei note.

Schlüssel, Werte oder Paare wählen

Für const scores = { Ana: 82, Ben: 74, Chen: 91 }; geben diese Funktionen Arrays der eigenen aufzählbaren Eigenschaften mit Zeichenkettenschlüsseln zurück:

AusdruckErgebnis
Object.keys(scores)["Ana", "Ben", "Chen"]
Object.values(scores)[82, 74, 91]
Object.entries(scores)[["Ana", 82], ["Ben", 74], ["Chen", 91]]

Das Objekt hat keine Länge wie ein Array: scores.length ist undefined. Object.keys(scores).length zählt drei Eigenschaften. Um die Punktzahlen zu summieren, reduziere die Werte mit null als Anfangswert. Ihre Summe ist 247 und ihr Mittelwert etwa 82,33.

Mit beiden Teilen eine Schleife durchlaufen
let bestName;
let bestScore = -Infinity;
for (const [name, score] of Object.entries(scores)) {
  if (score > bestScore) {
    bestName = name;
    bestScore = score;
  }
}

Die Schleife vergleicht 82, 74 und dann 91 mit der bisher höchsten Punktzahl. Am Ende stehen "Chen" und 91. Das Muster mit eckigen Klammern gibt den beiden Teilen jedes Paars Namen.

Ein einfaches Objekt ist nicht iterierbar, daher löst for...of scores einen TypeError aus. Object.entries(scores) liefert ein iterierbares Array. Die ältere for...in-Schleife liefert Zeichenkettenschlüssel und kann geerbte aufzählbare Eigenschaften einschließen.

Einträge zurück in ein Objekt umwandeln
const weightsG = { flour: 500, sugar: 250, salt: 5 };
const weightsKg = Object.fromEntries(
  Object.entries(weightsG).map(([item, g]) => [item, g / 1000])
);

entries erzeugt Paare, map ändert jeden Wert und behält seinen Schlüssel bei, und fromEntries erstellt den Datensatz erneut. Das Ergebnis ist { flour: 0.5, sugar: 0.25, salt: 0.005 }; weightsG bleibt unverändert.

Die Reihenfolge eigener Eigenschaften ist festgelegt. Arrayindexschlüssel von "0" bis "4294967294" erscheinen zuerst in aufsteigender Reihenfolge; andere Zeichenkettenschlüssel folgen in Einfügereihenfolge. Eine führende Null wie in "01" verhindert, dass ein Schlüssel ein Arrayindex ist. Daher ergibt Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }) den Wert ["1", "2", "b", "a"]. Verwende ein Array, wenn die Positionen eine Bedeutung haben.

Wichtige Erkenntnisse

  • Die Existenz einer Eigenschaft und ihr Wahrheitswert beantworten unterschiedliche Fragen.
  • Object.hasOwn prüft eigene Eigenschaften; in prüft auch geerbte.
  • Object.entries liefert Schlüssel-Wert-Paare für Schleifen und Transformationen.
  • Object.fromEntries erstellt aus Paaren wieder ein Objekt.
  • Arrayindexschlüssel stehen in der Eigenschaftsreihenfolge vor anderen Zeichenkettenschlüsseln.
  • Zähle eigene aufzählbare Zeichenkettenschlüssel mit Object.keys(obj).length.

1.3 Verstehe Referenzen, Kopieren und Vergleichen

Zwei Variablen können auf ein Objekt verweisen. Bevor du eine Aktualisierung vorhersagst, entscheide, ob der Code ein neues Objekt erstellt oder eine Referenz auf ein vorhandenes Objekt kopiert hat.

Identität und Daten getrennt verfolgen
const p1 = { x: 1 };
const p2 = p1;
p2.x = 99;
p1.x;       // 99
p1 === p2;  // true

Die Zuweisung hat die Referenz kopiert. Beide Namen führen zur selben Eigenschaft. Die Zuweisung primitiver Werte funktioniert anders: Nach let a = 5; let b = a; b = 6; bleibt a gleich 5.

Objekte werden sowohl mit === als auch mit == anhand ihrer Identität verglichen. Zwei Literale erstellen getrennte Objekte, selbst wenn alle Felder übereinstimmen: ({ x: 1 } === { x: 1 }) ist false. Um ihre Daten zu vergleichen, vergleiche die relevanten Eigenschaften. Eine übereinstimmende Darstellung bei der Ausgabe ist keine Identitätsprüfung.

Auch die Übergabe eines Objekts an eine Funktion kopiert seine Referenz. Eine Funktion, die order.status = "shipped"; ausführt, ändert das Objekt des Aufrufers. Gibt sie stattdessen { ...order, status: "shipped" } zurück, erstellt sie einen neuen Datensatz auf der obersten Ebene.

const, Einfrieren und Kopieren unterscheiden

const cart = { items: 2 }; erlaubt cart.items = 3;, aber die Neuzuweisung cart = {}; löst einen TypeError aus. Object.freeze(cart) verhindert Änderungen an den eigenen Eigenschaften des Objekts. Im strikten Modus lösen Versuche, sie hinzuzufügen, zu entfernen oder zu überschreiben, einen TypeError aus.

Das Einfrieren ist flach. Enthält ein eingefrorener Datensatz ein weiteres Objekt, können die Felder dieses verschachtelten Objekts weiterhin geändert werden. Ein eingefrorener Behälter und eine bis in die Tiefe unveränderliche Struktur sind verschiedene Dinge.

Eine flache Kopie verfolgen
const settings = { theme: "dark", font: { size: 14 } };
const copy = { ...settings };
copy.theme = "light";
copy.font.size = 18;

Spread erstellt ein neues äußeres Objekt. Sein theme-Wert wird kopiert, sodass eine Änderung von copy.theme den Wert von settings.theme bei "dark" belässt. Sein font-Wert ist eine Referenz, die in beide Datensätze kopiert wird. Eine Aktualisierung von copy.font.size setzt daher auch settings.font.size auf 18.

Auch Object.assign({}, settings) erstellt eine flache Kopie. Eine flache Kopie trennt den äußeren Datensatz ab, während die Identität verschachtelter Objekte und Arrays erhalten bleibt.

Verschachtelte Daten kopieren, wenn sie unabhängig sein müssen
const deep = structuredClone(settings);
deep.font.size = 22;
settings.font.size; // 18

structuredClone kopiert verschachtelte Objekte und Arrays sowie unterstützte Werte wie Map, Set und Date. Es verarbeitet auch zirkuläre Referenzen. Das neue verschachtelte font kann unabhängig geändert werden. Funktionen lassen sich auf diese Weise nicht klonen: Ein Objekt mit einer Methode verursacht einen DataCloneError.

Ein JSON-Roundtrip, JSON.parse(JSON.stringify(obj)), kopiert nur JSON-kompatible Daten. Er lässt Objekteigenschaften mit undefined oder Funktionen weg, wandelt Datumswerte in Zeichenketten um und verliert Einträge von Maps und Sets, sofern du sie nicht umwandelst. Wähle einen Klon für unabhängige unterstützte JavaScript-Daten und JSON, wenn du eine Textdarstellung erstellen möchtest.

Wichtige Erkenntnisse

  • Zuweisungen und Funktionsaufrufe kopieren Objektreferenzen.
  • Objekte werden anhand ihrer Identität verglichen, auch wenn ihre Felder übereinstimmen.
  • Eine flache Kopie nutzt verschachtelte Objekte gemeinsam mit dem Original.
  • Object.freeze verhindert Änderungen an eigenen Eigenschaften, wirkt aber nur flach.
  • structuredClone kopiert unterstützte verschachtelte Daten und lehnt Funktionen ab.

1.4 Arbeite mit verschachtelten Daten

Verschachtelte Daten kombinieren Datensätze und Listen. Lies einen Pfad Schritt für Schritt und prüfe, ob jeder Schritt zu einem Objekt, einem Array oder einem endgültigen Wert führt.

Eine Liste innerhalb eines Datensatzes lesen und verarbeiten
const order = {
  id: 1042,
  customer: { name: "Sara", city: "Lisbon" },
  items: [
    { product: "Tea", qty: 2, unitPrice: 4.5 },
    { product: "Mug", qty: 1, unitPrice: 9 }
  ]
};

order.customer.city liest "Lisbon". order.items[1].product wählt zuerst das items-Array, dann dessen zweiten Datensatz und schließlich "Mug" aus. order.items.length ist 2.

Die bereits bekannten Arraymethoden arbeiten mit Datensatzeigenschaften. map(item => item.product) erzeugt Produktnamen. filter(item => item.qty > 1) behält die Teeposition. find(item => item.product === "Mug") gibt den vorhandenen Tassendatensatz zurück. Änderst du diesen zurückgegebenen Datensatz, änderst du auch die Position in der Bestellung.

Um den Gesamtbetrag zu berechnen, verwende order.items.reduce((sum, item) => sum + item.qty * item.unitPrice, 0). Die erste Position addiert 9; die zweite addiert weitere 9, sodass 18 entsteht. Berechnest du den Gesamtbetrag bei Bedarf, verhinderst du, dass ein separat gespeicherter Gesamtbetrag nach einer Änderung der Positionen veraltet.

Optionale Daten mit einer Rückfalllösung lesen
order.shipping?.date;                 // undefined
order.customer?.city ?? "unknown";    // "Lisbon"

Die optionale Verkettung ?. bricht ab, wenn der Wert unmittelbar links davon null oder undefined ist. Ein direkter Zugriff mit order.shipping.date würde einen TypeError auslösen. Verwende an jedem optionalen Glied eines längeren Pfads eine Prüfung. Auch der Zugriff mit eckigen Klammern und Aufrufe unterstützen dies: order.items?.[0] und order.print?.().

Die optionale Verkettung ist für Werte gedacht, die fehlen dürfen. Für Pflichtfelder brauchst du weiterhin Prüfungen oder Fehler, die einen fehlerhaften Datensatz sichtbar machen. Sie kann nicht links von einer Zuweisung stehen: order.shipping?.date = "2026-05-01" ist ein Syntaxfehler.

Der Nullish-Coalescing-Operator ?? verwendet seine rechte Seite nur bei null oder undefined. Er behält null, false und "" bei. Für const qty = 0; bleibt qty ?? 1 gleich null, während qty || 1 zu 1 wird, weil || jeden Falsy-Wert ersetzt.

Eine geeignete Struktur wählen

Ein Array aus Datensätzen eignet sich zum Auflisten, Filtern und Ordnen. Ein Objekt mit IDs als Schlüsseln ermöglicht einen direkten Zugriff: usersById["u23"].name. Eine Map ist nützlich, wenn Suchschlüssel häufig hinzugefügt und entfernt werden.

Neueres JavaScript bietet Object.groupBy, das seit 2024 breit verfügbar ist:

const tasks = [
  { title: "Book flights", status: "done" },
  { title: "Pack", status: "todo" },
  { title: "Renew passport", status: "done" }
];
const grouped = Object.groupBy(tasks, task => task.status);

grouped.done enthält zwei Datensätze und grouped.todo einen. Das Ergebnis hat keinen Prototyp und daher keine geerbte toString-Methode. Eine ältere Alternative erstellt die Arrays für diese Statusschlüssel ausdrücklich:

const groupedOlder = tasks.reduce((groups, task) => {
  if (!Object.hasOwn(groups, task.status)) {
    groups[task.status] = [];
  }
  groups[task.status].push(task);
  return groups;
}, {});

Der erste Datensatz jeder Gruppe erstellt ihr Array. Spätere Datensätze werden an dasselbe Array angehängt. Dieser Akkumulator ist ein gewöhnliches Objekt; das Ergebnis der neueren Methode hat keinen Prototyp. Verwende einheitliche Namen und Werttypen in allen Datensätzen; Namen wie distanceKm und tempC halten außerdem die Einheiten sichtbar.

Wichtige Erkenntnisse

  • Lies einen verschachtelten Pfad vom äußeren Objekt zum benötigten Wert.
  • find gibt den vorhandenen Datensatz zurück, keine Kopie.
  • ?. bricht bei null oder undefined ab; ?? liefert dafür eine Rückfalllösung.
  • Verwende ein Array für eine geordnete Liste und Daten mit Schlüsseln für den direkten Zugriff.
  • Object.groupBy gruppiert Datensätze unter Schlüsseln in Arrays.
  • Einheitliche Feldnamen, Typen und Einheiten erleichtern die Verarbeitung von Datensätzen.
2

Gib Objekten mit Methoden und this ein Verhalten

Methoden ermöglichen es einem Objekt, seine Daten mit Aktionen zu verbinden, die diese Daten nutzen. Das kleine Wort this verbindet eine Aktion mit einem Objekt, doch sein Wert hängt davon ab, wie die Funktion ausgeführt wird. Du verfolgst gewöhnliche Methodenaufrufe, entliehene Methoden und Callbacks und wählst dann einen Wrapper oder eine gebundene Funktion, wenn eine Aktion ihr Objekt behalten muss. Die Beispiele laufen als Module, daher gilt der strikte Modus, sofern ein Beispiel nicht ausdrücklich nicht strikten Code verwendet.

2.1 Schreibe Methoden, die auf die Daten ihres Objekts zugreifen

Eine Methode ist eine Eigenschaft, deren Wert eine Funktion ist und die über ein Objekt aufgerufen wird. Sie ermöglicht einer Aktion, die aktuellen Daten des Datensatzes zu nutzen.

Eine Methode mit this schreiben
const counter = {
  count: 0,
  increment() {
    this.count += 1;
    return this.count;
  }
};
counter.increment(); // 1
counter.increment(); // 2

Die Kurzschreibweise increment() { ... } definiert eine Eigenschaft, deren Wert eine reguläre Funktion ist. In counter.increment() wird das Empfängerobjekt counter zu this. Jeder Aufruf liest den gespeicherten Zählerstand, addiert eins und gibt die neue Zahl zurück.

Ein allein stehendes count wählt eine Variable, nicht die Eigenschaft. Ohne passende Variable löst count += 1 einen ReferenceError aus. Verwende this.count, um auf das Feld des Empfängerobjekts zuzugreifen.

Eine Funktion lesen oder ausführen

counter.increment liest einen Wert vom Typ "function". Die Klammern in counter.increment() führen die Funktion aus und liefern ihren Rückgabewert. Wenn du eine Aktion zur späteren Verwendung übergibst, benötigt der empfangende Code die Funktion, nicht das Ergebnis ihrer sofortigen Ausführung.

Auch integrierte Methoden verwenden diese Aufrufform: Math.max(3, 7) gibt 7 und "abc".toUpperCase() gibt "ABC" zurück.

Eine Aktion wiederverwenden
function describe() {
  return this.name + " (" + this.year + ")";
}
const film = { name: "Up", year: 2009, describe };
const song = { name: "Hello", year: 2015, describe };

film.describe() gibt "Up (2009)" zurück; song.describe() gibt "Hello (2015)" zurück. Mit this kann dieselbe Funktion beide Empfängerobjekte lesen. Ein fest geschriebenes film.name würde sie an die Variable film binden.

Das Empfängerobjekt für eine weitere Aktion zurückgeben
const playlist = {
  tracks: [],
  add(title) { this.tracks.push(title); return this; },
  count() { return this.tracks.length; }
};
playlist.add("Rain").add("Waves").count(); // 2

Jeder add-Aufruf gibt die Wiedergabeliste zurück, sodass die nächste Methode auf diesem Objekt gesucht werden kann. Würde add eine Zahl zurückgeben, bräche die Kette ab, weil das nächste add auf dieser Zahl gesucht würde.

Die gewöhnliche JSON-Umwandlung lässt Methoden weg: Beim Umwandeln von { name: "Kit", hi() { return 1; } } in eine JSON-Zeichenkette wird nur name geschrieben. Das Parsen kann weggelassenen Code nicht wiederherstellen. Datensätze zum Speichern oder Austauschen enthalten häufig einfache Daten und verwenden separate Verarbeitungsfunktionen.

Wichtige Erkenntnisse

  • Eine Methode ist eine Eigenschaft, deren Wert eine Funktion ist und die über ein Objekt aufgerufen wird.
  • In obj.method() verwendet eine reguläre Methode obj als this.
  • Ein Funktionswert und das Ergebnis seines Aufrufs sind verschiedene Werte.
  • Die Rückgabe von this kann einen weiteren Methodenaufruf ermöglichen.
  • Die gewöhnliche JSON-Umwandlung lässt Eigenschaften weg, deren Wert eine Funktion ist.

2.2 Erkläre, wie der Wert von this bestimmt wird

Bei einer regulären Funktion bestimmt der Aufruf this. Das Speichern einer Funktion in einem Objekt bindet sie nicht dauerhaft an dieses Objekt.

Das Empfängerobjekt beim Aufruf verfolgen
const a = { n: "A", who() { return this.n; } };
const b = { n: "B" };
b.who = a.who;
a.who(); // "A"
b.who(); // "B"

Beide Eigenschaften enthalten dieselbe Funktion. Das Empfängerobjekt vor dem Punkt ist unterschiedlich, daher unterscheiden sich die Ergebnisse. Der ursprüngliche Ort der Funktion entscheidet nicht, welches Objekt sie liest.

Bei einem einfachen Aufruf f() liefert der strikte Modus undefined als this. JavaScript-Module laufen immer im strikten Modus; auch ein Skript oder eine Funktion kann mit "use strict"; beginnen. Eine nicht strikte reguläre Funktion, die einfach aufgerufen wird, verwendet stattdessen das globale Objekt globalThis. In einem Browser ist dieses globale Objekt window.

Den umgebenden Kontext einer Pfeilfunktion erkennen

Eine Pfeilfunktion hat kein eigenes this. Sie behält das this des umgebenden Codes, in dem sie erstellt wurde. Ein Objektliteral erzeugt keinen neuen this-Kontext.

// At the top level of a module:
const user = {
  name: "Ida",
  hi: () => "Hi, " + this.name
};

Der Aufruf von user.hi() löst einen TypeError aus: Die Pfeilfunktion hat das this der obersten Modulebene übernommen, das gleich undefined ist. Auch wenn der Aufruf wie ein Methodenaufruf aussieht, erhält die Pfeilfunktion dadurch kein neues Empfängerobjekt. Auf der obersten Ebene eines klassischen Skripts ist das umgebende this stattdessen das globale Objekt.

Verwende eine reguläre Methode, wenn die Aktion das aufrufende Objekt benötigt. Verwende eine Pfeilfunktion innerhalb dieser Methode, wenn ein Callback den Kontext der Methode behalten muss:

const group = {
  title: "Team",
  members: ["Ana", "Ben"],
  list() {
    return this.members.map(m => this.title + ": " + m);
  }
};
group.list(); // ["Team: Ana", "Team: Ben"]

list erhält group durch seinen Methodenaufruf. Die Pfeilfunktion wird innerhalb dieser laufenden Methode erstellt und behält dasselbe this. Einem strikten regulären Callback ohne übergebenes Empfängerobjekt würde undefined zugewiesen, sodass this.title dort fehlschlagen würde.

Eine Entscheidungsreihenfolge verwenden

Wenn du einem Aufruf begegnest, bestimme zuerst die aufgerufene Funktion:

  1. Eine Pfeilfunktion behält ihr umgebendes this; call, apply und bind können es nicht ersetzen.
  2. Eine gebundene reguläre Funktion behält ihr gebundenes this, auch bei call oder apply.
  3. Eine ungebundene reguläre Funktion, die mit call oder apply aufgerufen wird, verwendet das übergebene this.
  4. Ein gewöhnlicher Aufruf obj.method() verwendet obj.
  5. Ein einfacher regulärer Aufruf verwendet im strikten Modus undefined oder im nicht strikten Modus das globale Objekt.

Callbacks können von ihrem Aufrufer ein Empfängerobjekt erhalten. Ein regulärer DOM-Event-Listener, der mit addEventListener registriert wird, erhält beispielsweise das Element, an dem er registriert ist, als this. Lies nach, wie der empfangende Code einen Callback aufruft, bevor du von einem einfachen Aufruf ausgehst.

Wichtige Erkenntnisse

  • Eine reguläre Funktion erhält this durch ihren Aufruf; wird eine Methode entliehen, ändert sich daher ihr Empfängerobjekt.
  • Ein einfacher Aufruf im strikten Modus verwendet undefined als this.
  • Eine Pfeilfunktion behält das umgebende this der Stelle, an der sie erstellt wurde.
  • Ein gebundenes Empfängerobjekt hat Vorrang vor einem späteren call oder apply.
  • Eine Pfeilfunktion innerhalb einer regulären Methode kann das this dieser Methode behalten.

2.3 Behalte den Wert von this bei, wenn du Methoden als Callbacks übergibst

Wird eine Methode aus ihrem Objekt herausgelöst, bleibt die Funktion erhalten, aber der ursprüngliche Aufrufausdruck geht verloren. Ein Callback muss so aufgerufen werden, dass er das benötigte Objekt erhält.

Eine losgelöste Methode untersuchen
const counter = {
  count: 0,
  increment() {
    this.count += 1;
    return this.count;
  }
};
const inc = counter.increment;
inc(); // TypeError in strict mode

inc() ist ein einfacher Aufruf, daher ist this gleich undefined. Das Lesen von this.count schlägt fehl, bevor eine Erhöhung stattfinden kann. In nicht striktem Code verwendet ein einfacher Aufruf das globale Objekt und schreibt möglicherweise stattdessen ein globales count; er greift nicht auf den Zähler zu.

Dasselbe Problem tritt bei Array-Callbacks auf. [1, 2].map(counter.increment) übergibt eine Funktion ohne ihr ursprüngliches Empfängerobjekt an map. Die als Argumente übergebenen Arraywerte liefern kein this.

Den Methodenaufruf umschließen
const results = [1, 2].map(() => counter.increment());
// results is [1, 2]; counter.count is 2

Der Callback ist eine Pfeilfunktion, die einen normalen Aufruf counter.increment() ausführt. Dieser Aufruf hat ein Empfängerobjekt. Der Wrapper ignoriert bewusst die von map übergebenen Werte; jeder Aufruf erhöht den Zähler einfach einmal. Diese Form ist praktisch, wenn der Callback nur an einer Stelle benötigt wird.

Eine wiederverwendbare Funktion binden

Beginne mit einem neuen Zähler bei null:

const boundInc = counter.increment.bind(counter);
const results = [1, 2].map(boundInc);
// results is [1, 2]; counter.count is 2

bind gibt eine neue Funktion zurück; es ruft die Methode noch nicht auf. Die neue Funktion behält counter als Empfängerobjekt. Eine erneute Bindung an ein anderes Objekt kann dieses Empfängerobjekt nicht ersetzen. Jeder Aufruf von bind erstellt eine eigene Funktion. Speichere daher das Ergebnis, wenn der Code später genau denselben Callback wiedererkennen muss.

Beim Binden lassen sich auch die ersten Argumente festlegen. Auf function multiply(a, b) { return a * b; } folgt const double = multiply.bind(null, 2);, sodass double(21) den Wert 42 zurückgibt. null belegt die Position des Empfängerobjekts, weil diese Funktion kein this verwendet; 2 belegt ihren ersten gewöhnlichen Parameter.

Einmal mit call oder apply ausführen
function describe(unit) {
  return this.value + " " + unit;
}
describe.call({ value: 12 }, "kg");    // "12 kg"
describe.apply({ value: 12 }, ["kg"]); // "12 kg"

Beide Formen führen die Funktion sofort mit dem gewählten Empfängerobjekt aus. call übergibt Argumente einzeln; apply übergibt sie in einem Array. Der Kontext einer Pfeilfunktion wird durch ihre Umgebung festgelegt, sodass diese Methoden ihr this nicht ersetzen können.

Wird counter.increment() als Callback übergeben, führt das die Methode sofort aus und übergibt die zurückgegebene Zahl. Das ist nicht die Funktion, die map benötigt. Bei einer Ereignisregistrierung wie button.addEventListener("click", counter.increment()) ändert sich der Zähler sofort und der numerische Listener verursacht einen TypeError. Übergib einen Funktionswert, einen Pfeilfunktions-Wrapper oder eine gespeicherte gebundene Funktion.

Wichtige Erkenntnisse

  • Wird eine Methode herausgelöst, verliert sie ihr ursprüngliches Empfängerobjekt.
  • Ein Pfeilfunktions-Wrapper kann den benötigten Methodenaufruf später ausführen.
  • bind erstellt eine Funktion mit einem festen Empfängerobjekt und optional festgelegten ersten Argumenten.
  • call und apply führen die Funktion sofort aus; sie unterscheiden sich darin, wie sie Argumente entgegennehmen.
  • Callback-Argumente müssen Funktionen sein, nicht das numerische Ergebnis eines Methodenaufrufs.
3

Entpacke und kombiniere Daten mit Destrukturierung, Spread und Rest

Die Destrukturierung gibt ausgewählten Teilen eines Objekts oder einer geordneten Sammlung Namen. Spread erstellt Werte aus vorhandenen Teilen, während Rest die übrigen Teile sammelt. Diese Formen treten häufig gemeinsam in Funktionen auf, die Optionen entgegennehmen oder aktualisierte Datensätze zurückgeben. Wenn du genau auf ihre Position achtest, kannst du vorhersagen, welche Variablen existieren, welche Standardwerte gelten und ob verschachtelte Daten gemeinsam mit dem Original genutzt werden.

3.1 Destrukturiere Objekte

Die Objektdestrukturierung liest benannte Felder in lokale Variablen. Sie wählt Werte aus, ohne den gesamten Quelldatensatz zu kopieren.

Zuordnen und umbenennen
const book = { title: "Dune", pages: 412 };
const { pages, title: bookTitle, rating: stars = 0 } = book;

Die Zuordnung erfolgt anhand der Eigenschaftsnamen, nicht ihrer Reihenfolge. Dies deklariert pages mit dem Wert 412, bookTitle mit "Dune" und stars mit 0. Es wird keine Variable title oder rating deklariert: Der Name nach einem Doppelpunkt ist die lokale Zielvariable.

Ein fehlendes Feld liefert undefined. Ein Standardwert ersetzt nur undefined und behält null, null als Zahl, false und leere Zeichenketten bei. const { a = 5 } = { a: null }; belässt a daher bei null.

Verschachtelte Felder verfolgen
const data = {
  location: { name: "Oslo" },
  current: { tempC: -3, windKph: 18 }
};
const {
  location: { name },
  current: { tempC, windKph: wind }
} = data;

Die deklarierten Variablen sind name, tempC und wind mit den Werten "Oslo", -3 und 18. Die umgebenden Namen location und current wählen Pfade aus; sie werden nicht ebenfalls zu Variablen.

Fehlt ein äußeres Objekt, schlägt ein verschachtelter Lesezugriff fehl. const { shipping: { date } } = {}; löst einen TypeError aus. Gib einen äußeren Standardwert an, wenn dieses Feld undefined sein kann:

const { shipping: { date } = {} } = {};
// date is undefined

Dies ersetzt shipping nicht, wenn sein Wert null ist. Auch die direkte Destrukturierung von null oder undefined löst einen Fehler aus. Der Ausgangswert muss daher verwendbar sein, bevor das Entpacken beginnt.

Benannte Optionen entgegennehmen
function formatUser({ name, age = "unknown" }) {
  return name + ", " + age;
}

formatUser({ name: "Mo" }) gibt "Mo, unknown" zurück. Werden die Felder wie in { age: 40, name: "Ines" } umgeordnet, ist der Rückgabewert weiterhin "Ines, 40". Ein Aufruf von formatUser ohne Argument schlägt fehl, weil kein Objekt zum Entpacken vorhanden ist. Ein Standardwert für den gesamten Parameter erlaubt diesen Aufruf:

function greet({ name = "guest" } = {}) {
  return "Hi, " + name;
}
greet(); // "Hi, guest"

Der äußere Standardwert behandelt ein ausgelassenes Argument; der innere behandelt einen fehlenden Namen. Die Übergabe von null schlägt weiterhin fehl. Um vorhandenen Variablen Werte zuzuweisen, setze eine Anweisung mit Objektmuster in runde Klammern: let x, y; ({ x, y } = { x: 4, y: 7 });. Andernfalls werden die anfänglichen geschweiften Klammern als Anweisungsblock gelesen.

Wichtige Erkenntnisse

  • Objektmuster ordnen Eigenschaften anhand ihres Namens zu.
  • Ein Doppelpunkt benennt die Variable um; er ändert nicht den Schlüssel im Ausgangsobjekt.
  • Standardwerte ersetzen undefined, auch bei fehlenden Eigenschaften, und behalten null bei.
  • Verschachtelte Muster benötigen auf jeder Ebene ein verwendbares Objekt.
  • Ein Standardwert für den gesamten Parameter und ein Standardwert für eine Eigenschaft behandeln unterschiedliche fehlende Werte.
  • Runde Klammern ermöglichen es einem Objektmuster, vorhandenen Variablen Werte zuzuweisen.

3.2 Destrukturiere Arrays und andere iterierbare Objekte

Die Array-Destrukturierung liest Werte anhand ihrer Position aus einem iterierbaren Objekt. Kommas steuern, welche Werte ausgewählt werden; die Variablennamen wählen keine Positionen aus.

Positionen auswählen oder überspringen
const medals = ["gold", "silver", "bronze"];
const [first, second] = medals;
const [, , third] = medals;

Die Variablen erhalten "gold", "silver" und "bronze". Leere Stellen verbrauchen Werte, ohne Variablen zu deklarieren. Ein Name, für den kein Wert mehr vorhanden ist, erhält undefined. Standardwerte ersetzen nur undefined:

const [p, q = 10] = [1]; // p is 1; q is 10
const [r = 10] = [null]; // r is null
Die übrigen Werte sammeln
const [head, ...tail] = [1, 2, 3, 4];
// head is 1; tail is [2, 3, 4]

Das abschließende Restelement erstellt ein neues Array, das leer ist, wenn nichts übrig bleibt. Es muss zuletzt stehen. Objektwerte innerhalb dieses Arrays behalten ihre Identität; beim Sammeln werden sie nicht tief geklont.

Ein zurückgegebenes Paar lesen oder Variablen vertauschen
function minMax(nums) {
  return [Math.min(...nums), Math.max(...nums)];
}
const [lo, hi] = minMax([4, 9, 1]);
// lo is 1; hi is 9

Der Aufrufer hält sich an die von der zurückgebenden Funktion festgelegte Reihenfolge. Bei vielen Ergebnisfeldern ersparen benannte Objekteigenschaften das Merken von Positionen.

Mit let x = 1, y = 2; vertauscht [x, y] = [y, x]; die Variablen. Das Array auf der rechten Seite wird vor jeder der beiden Zuweisungen als [2, 1] ausgewertet. So bleiben beide alten Werte ohne temporäre Variable erhalten.

Andere iterierbare Objekte entpacken

Auch Zeichenketten und Sets lassen sich entpacken: const [initial] = "Zoe"; ergibt "Z". Sets liefern Werte in Einfügereihenfolge. Map-Einträge sind geordnete Paare:

const distances = new Map([["park", 2], ["lake", 5]]);
for (const [place, distanceKm] of distances) {
  console.log(place, distanceKm);
}

Die Schleife erhält ein Paar, dann trennt das Muster dessen Schlüssel und Wert. Object.entries liefert Paare in derselben Form.

Ein einfaches Objekt ist nicht iterierbar, daher löst const [name] = { name: "Ana" }; einen TypeError aus. Verwende geschweifte Klammern, um sein benanntes Feld auszuwählen: const { name } = { name: "Ana" };. Eckige Klammern benötigen eine Folge von Werten; geschweifte Klammern wählen Eigenschaften anhand ihres Namens aus.

Wichtige Erkenntnisse

  • Arraymuster ordnen anhand von Positionen zu, und leere Stellen überspringen Werte.
  • Eine fehlende Position ergibt undefined, sofern kein Standardwert es ersetzt.
  • Ein abschließendes Restelement sammelt die übrigen Werte in einem neuen Array.
  • Arraymuster funktionieren auch mit Zeichenketten, Sets und Map-Einträgen.

3.3 Kopiere, führe zusammen und sammle mit Spread und Rest

Die drei Punkte ... haben zwei verwandte Aufgaben. Spread entfaltet vorhandene Daten in einem Wert oder Aufruf. Rest sammelt Werte in einer Variablen, wo ein Muster oder Parameter sie deklariert.

Nach Priorität zusammenführen
const defaults = { lang: "en", units: "metric", alerts: true };
const user = { lang: "pt", alerts: false };
const options = { ...defaults, ...user };
// { lang: "pt", units: "metric", alerts: false }

Objekt-Spread kopiert eigene aufzählbare Eigenschaften. Wenn ein Schlüssel erneut erscheint, setzt sich der spätere Wert durch. Stünde user vor defaults, würden die Einstellungen des Nutzers überschrieben. Werden null oder undefined mit Spread in ein Objekt übernommen, wird nichts hinzugefügt.

Spread-Kopien sind flach. Wenn sich ein verschachtelter Datensatz ändert, kopiere auch diese Ebene:

const settings = { theme: "dark", font: { size: 14, family: "serif" } };
const next = {
  ...settings,
  font: { ...settings.font, size: 18 }
};

Der äußere Spread behält theme bei. Der innere Spread behält family bei und ersetzt size. settings.font.size bleibt 14, weil der geänderte verschachtelte Datensatz neu ist.

Einen Datensatz in einer Liste ersetzen
const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map(t =>
  t.id === 2 ? { ...t, done: true } : t
);

map erstellt ein neues Array. Das passende Element wird zu einem neuen Objekt, daher ist updated[1].done gleich true, während todos[1].done gleich false bleibt. Das unveränderte erste Element wird wiederverwendet: updated[0] === todos[0] ist true. Für unabhängige Aktualisierungen müssen unveränderte Datensätze nicht kopiert werden.

Werte aus iterierbaren Objekten entfalten

In einem Arrayliteral oder Funktionsaufruf entnimmt Spread einem iterierbaren Objekt Werte. [...a, ...b] verbindet deren Werte zu einem neuen Array. Math.max(...[4, 9, 1]) übergibt drei Argumente und gibt 9 zurück. Ein einfaches Objekt lässt sich nicht in ein Array entfalten: [...{ a: 1 }] löst einen TypeError aus. Für Objekt-Spread und Spread iterierbarer Objekte gelten unterschiedliche Regeln dafür, was sie lesen.

Argumente oder übrige Eigenschaften sammeln
function total(...nums) {
  return nums.reduce((sum, n) => sum + n, 0);
}
total(2, 3, 5); // 10
total();        // 0

Ein Restparameter erhält ein echtes Array, auch wenn er keine Werte erhält. Er muss der letzte Parameter sein und es darf nur einen geben. Das ältere arguments-Objekt ist kein echtes Array. Pfeilfunktionen haben kein eigenes arguments, können aber die Bindung einer umgebenden regulären Funktion lesen.

Objekt-Rest sammelt eigene aufzählbare Eigenschaften, die noch nicht ausgewählt wurden:

const userRecord = { id: 8, name: "Rae", password: "x9!k" };
const { password, ...publicUser } = userRecord;
// publicUser is { id: 8, name: "Rae" }

Dies erstellt einen neuen Datensatz und lässt den Ausgangsdatensatz unverändert. Die Rest-Eigenschaft muss zuletzt stehen. An der Position erkennst du die Aufgabe: Drei Punkte in einem Literal oder Aufruf entfalten Werte nach außen; drei Punkte in einer Parameterliste oder einem Destrukturierungsziel sammeln Werte nach innen.

Wichtige Erkenntnisse

  • Bei überlappenden Objekt-Spreads setzen sich spätere Eigenschaften durch.
  • Kopiere jede verschachtelte Ebene, die unabhängig geändert werden muss.
  • Spread in Arrays und Aufrufen benötigt ein iterierbares Objekt.
  • Rest sammelt übrige Argumente, Elemente oder Eigenschaften und muss zuletzt stehen.
  • Eine Aktualisierung mit map kann einen geänderten Datensatz kopieren und unveränderte Datensätze wiederverwenden.
  • Restparameter sind echte Arrays; das ältere arguments-Objekt ist keines.
4

Speichere Sammlungen mit Map und Set

Manche Sammlungen benötigen Schlüssel, die Objekte oder Zahlen sind, andere sollen jeden Wert nur einmal enthalten. Map und Set erfüllen diese Anforderungen direkt. Du erstellst Einträge, prüfst die Zugehörigkeit, verfolgst die Einfügereihenfolge und wandelst Sammlungen in Arrays oder Objekte um, wenn eine andere Operation diese Form benötigt. Gleichheit bleibt dabei wichtig: Zwei Datensätze mit übereinstimmenden Feldern können in beiden Sammlungen zwei getrennte Werte bleiben.

4.1 Speichere Schlüssel-Wert-Paare in einer Map

Eine Map speichert Zuordnungen zwischen Schlüsseln und Werten. Anders als die Zeichenkettenschlüssel eines einfachen Objekts kann ein Map-Schlüssel eine Zahl, ein Objekt oder ein anderer Wert sein, ohne in eine Zeichenkette umgewandelt zu werden.

Einträge erstellen und verwalten
const stock = new Map();
stock.set("apples", 12).set("pears", 7);
stock.get("apples"); // 12
stock.has("kiwis");  // false
stock.size;           // 2

set fügt einen Eintrag hinzu oder ersetzt seinen Wert und gibt die Map für eine Verkettung zurück. get gibt für einen fehlenden Schlüssel undefined zurück; verwende has, um ihn von einem Eintrag mit dem Wert undefined zu unterscheiden. delete(key) gibt zurück, ob es einen Eintrag entfernt hat, und clear() leert die Sammlung.

Die Klammernotation greift auf einen anderen Speicherbereich zu: stock["plums"] = 5; fügt dem Map-Objekt eine gewöhnliche Eigenschaft hinzu. Es entsteht kein Eintrag, der für get, has oder size sichtbar ist. Verwende für Einträge die Map-Methoden.

Schlüsseltypen und Identitäten erhalten

m.set(1, "number"); m.set("1", "text"); erstellt zwei Einträge. Die Schlüssel 1 und "1" eines einfachen Objekts würden auf eine Eigenschaft verweisen. Map-Schlüssel werden wie bei === verglichen, außer dass NaN mit sich selbst übereinstimmt und Nullen mit unterschiedlichem Vorzeichen denselben Schlüssel bilden.

const person = { id: 1 };
const notes = new Map([[person, "ready"]]);
notes.get(person);      // "ready"
notes.get({ id: 1 });   // undefined

Die zweite Abfrage erstellt ein neues Objekt. Übereinstimmende Felder machen es nicht zu demselben Schlüssel. Bewahre die ursprüngliche Objektreferenz auf und verwende sie erneut, wenn du ein Objekt als Schlüssel nutzt.

Paare durchlaufen und umwandeln
for (const [name, count] of stock) {
  console.log(name, count);
}

Eine Map liefert [key, value]-Paare in der Reihenfolge, in der die Schlüssel erstmals eingefügt wurden. Das Ersetzen eines Werts verschiebt seinen Schlüssel nicht. keys(), values() und entries() geben iterierbare Ansichten zurück, die du durchlaufen oder mit Spread in Arrays übernehmen kannst. forEach übergibt seinem Callback zuerst den Wert und dann den Schlüssel.

new Map(Object.entries(obj)) wandelt die Einträge eines Datensatzes in eine Map um. Object.fromEntries(map) erstellt ein Objekt; verwende es bei Zeichenkettenschlüsseln, weil Objektschlüssel nicht jeden Map-Schlüsseltyp erhalten können. [...map] erstellt ein Array aus Paaren, das sich zum Speichern von Map-Einträgen als JSON eignet.

Wechselnde Schlüssel zählen
const words = "the cat saw the dog and the bird".split(" ");
const counts = new Map();
for (const word of words) {
  counts.set(word, (counts.get(word) ?? 0) + 1);
}

Das erste Vorkommen beginnt bei null und addiert dann eins. Spätere Vorkommen lesen und erhöhen den gespeicherten Zähler. counts.get("the") ist 3 und counts.size ist 6: Die Größe zählt unterschiedliche Wörter, nicht alle acht Vorkommen.

Wähle ein einfaches Objekt für einen Datensatz mit bekannten Feldern, insbesondere für JSON-geeignete Daten. Wähle eine Map für wechselnde Schlüssel, häufige Größenprüfungen oder Schlüssel, deren Typ erhalten bleiben muss. Das neuere Map.groupBy erhält die Typen der Gruppenschlüssel:

const owner = { name: "Ari" };
const jobs = [{ owner, done: false }, { owner, done: true }];
const byOwner = Map.groupBy(jobs, job => job.owner);
byOwner.get(owner).length; // 2

Durchlaufe in älterem Code die Aufträge. Verwende für jeden Eigentümer has und set, um einmalig ein Gruppenarray zu erstellen, und dann get(owner).push(job), um den Datensatz hinzuzufügen. Wird der Eigentümer als Objektschlüssel verwendet, werden verschiedene Eigentümer auch dann unterschieden, wenn ihre Namensfelder übereinstimmen. Eine WeakMap kann Objekten Metadaten zuordnen, ohne anderweitig unerreichbare Schlüsselobjekte am Leben zu halten. Sie lässt sich nicht durchlaufen und hat keine Größe. Moderne WeakMaps akzeptieren auch nicht registrierte Symbole als Schlüssel.

Wichtige Erkenntnisse

  • Map-Schlüssel behalten ihre Typen; Objekte werden anhand ihrer Identität verglichen.
  • Verwende für Einträge set, get, has und delete, nicht die Klammernotation.
  • size zählt Einträge und beim Durchlaufen gilt die Einfügereihenfolge der Schlüssel.
  • Maps werden über Schlüssel-Wert-Paare umgewandelt.
  • Eine WeakMap kann Metadaten zu Objekten speichern, ohne die Schlüsselobjekte am Leben zu halten.
  • Map.groupBy erhält die Typen der Gruppenschlüssel in einer neueren Gruppierungs-API.

4.2 Speichere eindeutige Werte in einem Set

Ein Set speichert eindeutige Werte. Seine wichtigsten Fragen sind, ob ein Wert vorhanden ist und wie sich zwei Sammlungen überschneiden.

Werte hinzufügen und prüfen
const tags = new Set(["js", "css", "js"]);
tags.size;       // 2
tags.add("html");
tags.has("css"); // true

Das Hinzufügen eines vorhandenen Werts ändert nichts. add gibt das Set für eine Verkettung zurück. delete(value) gibt zurück, ob der Wert entfernt wurde, während clear() alle Werte entfernt. Der Konstruktor nimmt ein iterierbares Objekt entgegen: Verwende new Set([1, 2, 3]). new Set(1, 2, 3) löst einen TypeError aus, weil seine erste Eingabe nicht iterierbar ist. Eine Zeichenkette ist iterierbar, daher enthält new Set("hello") die Werte "h", "e", "l" und "o".

Ein Set hat keine Positionen mit Indizes. tags[0] ist undefined. Durchlaufe es mit for...of, rufe forEach auf oder wandle es für Operationen wie map und filter in ein Array um. Beim Durchlaufen gilt die Einfügereihenfolge; wird ein Wert entfernt und erneut hinzugefügt, steht er am Ende.

Duplikate ohne Sortieren entfernen
const unique = [...new Set([3, 1, 3, 2, 1])];
// [3, 1, 2]

Das Set behält das erste Vorkommen jedes Werts. Spread überträgt diese Werte in ein Array. Array.from(set) führt dieselbe Umwandlung durch.

Werte werden wie bei === verglichen, außer dass NaN mit sich selbst übereinstimmt; Nullen mit unterschiedlichem Vorzeichen zählen als ein Wert. Objektwerte werden anhand ihrer Identität verglichen: new Set([{ id: 1 }, { id: 1 }]).size ist 2. Um einen Datensatz pro ID zu behalten, erstelle eine Map mit dieser ID als Schlüssel und lies dann ihre Werte. Spätere Datensätze mit derselben ID ersetzen frühere, weil set einen vorhandenen Eintrag aktualisiert.

Bei wiederholten Zugehörigkeitsprüfungen in großen Sammlungen vermeidet ein Set die Einzelprüfung durch includes eines Arrays. Verwende es, wenn die Anwesenheit wichtiger ist als die Position.

Zwei Sammlungen vergleichen

Neuere Set-Methoden sind seit 2024 in den großen Browsern verfügbar. Dabei enthalte a die Werte 1, 2, 3, 4 und b die Werte 3, 4, 5:

OperationBedeutungErgebniswerte
a.union(b)In mindestens einer Sammlung1, 2, 3, 4, 5
a.intersection(b)In beiden3, 4
a.difference(b)In a, aber nicht in b1, 2
a.symmetricDifference(b)In genau einer1, 2, 5

Diese Operationen geben neue Sets zurück. isSubsetOf prüft, ob jeder Wert in der anderen Sammlung enthalten ist. isSupersetOf prüft die umgekehrte Beziehung. isDisjointFrom prüft, ob die Sammlungen keine gemeinsamen Werte haben. Alle drei geben boolesche Werte zurück. Zum Beispiel ist new Set([3, 4]).isSubsetOf(a) gleich true. Die Differenz hat eine Richtung: Werte in b, aber nicht in a ergäben nur 5.

In einer älteren Umgebung lässt sich eine Schnittmenge als new Set([...a].filter(x => b.has(x))) schreiben.

Das gewöhnliche JSON.stringify(set) erzeugt "{}", wobei die gespeicherten Werte verloren gehen. Wandle das Set vor dem Schreiben von JSON in ein Array um und verwende beim Lesen new Set(parsedArray). Ein WeakSet kann Objekte als verarbeitet markieren, ohne anderweitig unerreichbare Objekte am Leben zu halten. Es lässt sich nicht durchlaufen. Moderne WeakSets akzeptieren auch nicht registrierte Symbole.

Wichtige Erkenntnisse

  • Ein Set speichert jeden unterschiedlichen Wert einmal und prüft mit has, ob er vorhanden ist.
  • Wandle ein Set für den Zugriff über Indizes oder für Arraymethoden in ein Array um.
  • Objektwerte bleiben getrennt, sofern ihre Referenzen nicht übereinstimmen.
  • Vereinigungsmenge, Schnittmenge, Differenzmenge und symmetrische Differenz beantworten unterschiedliche Fragen zur Zugehörigkeit.
  • Die Differenz hängt davon ab, welches Set zuerst steht.
  • Wandle Set-Werte vor dem Schreiben von JSON in ein Array um.
  • Ein WeakSet kann Objekte markieren, ohne sie am Leben zu halten.
5

Wandle Daten in JSON und JSON in Daten um

JSON überträgt strukturierte Daten als Text. Die Umwandlung zwischen diesem Text und JavaScript-Werten zur Laufzeit ist nur dann nützlich, wenn du weißt, welche Informationen dabei erhalten bleiben. Du lernst, gültiges JSON zu erkennen, das Schreiben von Werten zu steuern und fehlerhafte Eingaben beim Lesen zu behandeln. Auch nach erfolgreichem Parsen muss die Struktur geprüft werden, bevor das Programm auf die Felder vertraut; gültiger Text allein kann die erwarteten Daten nicht garantieren.

5.1 Lies und schreibe Daten im JSON-Format

JSON, kurz für JavaScript Object Notation, ist ein sprachunabhängiges Textformat für strukturierte Daten. Ein Objekt ist ein JavaScript-Wert zur Laufzeit; JSON ist Text, der einen solchen Wert beschreiben kann.

Die sechs Wertarten erkennen

JSON unterstützt Objekte, Arrays, Zeichenketten, Zahlen, boolesche Werte und null. Jeder dieser Werte kann auf oberster Ebene stehen. Der Text 42 ist auch ohne geschweifte Klammern gültiges JSON. JSON hat keine Darstellung für Funktionen, undefined, Datumswerte als eigenen Typ, Map, Set, NaN oder Infinity.

{
  "name": "Amara",
  "age": 34,
  "languages": ["en", "yo"],
  "address": null,
  "member": true
}

Dieselben Grundideen zur Struktur finden sich in JavaScript-Literalen, aber die erlaubte Schreibweise ist strenger. JSON wird in Konfigurationen und beim Datenaustausch verwendet. Ausgetauschtes JSON verwendet die UTF-8-Kodierung und den Medientyp application/json; JSON-Dateien verwenden die Endung .json.

Die Syntaxregeln anwenden

Jeder Objektschlüssel muss eine Zeichenkette in doppelten Anführungszeichen sein. Auch Zeichenketten benötigen doppelte Anführungszeichen. Kommas trennen Eigenschaften oder Arrayelemente, aber nach dem letzten Element darf kein Komma stehen. Kommentare sind verboten. Leerraum zwischen Werten und Satzzeichen ist erlaubt.

TextWarum er fehlschlägt
{name: "Amara"}Dem Schlüssel fehlen doppelte Anführungszeichen.
{'name': 'Amara'}Einfache Anführungszeichen begrenzen keine JSON-Zeichenketten.
{"a": 1,}Auf das letzte Komma folgt keine Eigenschaft.
{"a": undefined}Undefined ist kein JSON-Wert.

Zahlen verwenden die Dezimalschreibweise. 1.5e3, -0.25 und 0 sind gültig. 07, +1 und 0x1F sind ungültig, weil JSON führende Nullen, ein führendes Pluszeichen und die Hexadezimalschreibweise verbietet.

Zeichen innerhalb von Zeichenketten maskieren

Verwende innerhalb einer JSON-Zeichenkette \" für ein doppeltes Anführungszeichen, \\ für einen umgekehrten Schrägstrich, \n für einen Zeilenumbruch und \t für einen Tabulator. Ein tatsächlicher Zeilenumbruch darf innerhalb einer JSON-Zeichenkette nicht vorkommen. Lass JSON.stringify Escape-Sequenzen aus tatsächlichen Zeichenkettenwerten erzeugen, damit eingebettete Anführungszeichen die Ausgabe nicht beschädigen können.

Eine Unicode-Escape-Sequenz besteht aus einem umgekehrten Schrägstrich, dem Buchstaben u und vier Hexadezimalziffern für eine UTF-16-Codeeinheit. Zum Beispiel stellt \u00e9 das Zeichen é dar. Ein Zeichen außerhalb dieses Bereichs kann zwei solche Escape-Sequenzen benötigen; es kann auch direkt in die Zeichenkette geschrieben werden. Die Anführungszeichen um JSON-Text im JavaScript-Quellcode bilden eine eigene Ebene gegenüber den Anführungszeichen innerhalb des JSON-Texts selbst.

Bezeichner erhalten und doppelte Schlüssel vermeiden

JavaScript-Zahlen erhalten jede ganze Zahl im sicheren Bereich von -9007199254740991 bis einschließlich 9007199254740991 exakt. Außerhalb dieses Bereichs bleiben manche ganzen Zahlen exakt und andere werden gerundet. Das Parsen von '{"id":9007199254740993}' ergibt für id den Wert 9007199254740992. Speichere lange Bezeichner als JSON-Zeichenketten, wenn ihre exakten Ziffern wichtig sind.

Objektschlüssel sollten innerhalb jedes JSON-Objekts eindeutig sein. Das JavaScript-Verfahren JSON.parse behält das letzte Vorkommen, wenn ein Schlüssel wiederholt wird: Das Parsen von '{"a":1,"a":2}' erzeugt { a: 2 }. Aus diesem wiederholten Namen lassen sich getrennte Eigenschaften nicht wiederherstellen.

Wichtige Erkenntnisse

  • JSON ist Text mit sechs Wertarten, darunter primitive Werte auf oberster Ebene.
  • Schlüssel und Zeichenketten benötigen doppelte Anführungszeichen; Kommentare und abschließende Kommas sind ungültig.
  • JSON-Zahlen schließen Hexadezimalschreibweise, führende Pluszeichen und führende Nullen aus.
  • Escape-Sequenzen stellen Sonderzeichen innerhalb von Zeichenketten dar.
  • Verwende Zeichenketten für lange Bezeichner, deren exakte Ziffern erhalten bleiben müssen.
  • Wiederholte Objektschlüssel sind unsicher; JSON.parse behält den letzten Wert.

5.2 Wandle Werte mit JSON.stringify in JSON-Text um

JSON.stringify wandelt unterstützte JavaScript-Werte in JSON-Text um. Entscheide vor dem Umwandeln eines Datensatzes mit Methoden oder Sammlungswerten, was der Text erhalten muss.

Kompakten oder eingerückten Text schreiben
const person = { name: "Amara", age: 34, tags: ["admin"] };
const text = JSON.stringify(person);
// '{"name":"Amara","age":34,"tags":["admin"]}'

Das Ergebnis ist eine Zeichenkette, daher ist typeof text gleich "string". Eigene aufzählbare Eigenschaften mit Zeichenkettenschlüsseln werden in der Reihenfolge von Object.keys geschrieben. JSON.stringify(person, null, 2) fügt Zeilenumbrüche und zwei Leerzeichen Einrückung pro Ebene hinzu. Das zweite Argument ist null, weil kein replacer-Parameter verwendet wird. Die numerische Einrückung ist auf 10 Leerzeichen begrenzt; von einer zur Einrückung verwendeten Zeichenkette werden höchstens die ersten 10 Zeichen verwendet.

Weggelassene und geänderte Werte vorhersagen
const data = {
  a: undefined,
  b: () => 1,
  c: NaN,
  d: [undefined, Infinity]
};
JSON.stringify(data); // '{"c":null,"d":[null,null]}'

Eine Objekteigenschaft mit undefined, einer Funktion oder einem Symbol wird weggelassen. In einem Array wird ein solcher Wert zu null, sodass die Position erhalten bleibt. NaN und Infinity werden an beiden Stellen zu null. Auf oberster Ebene führen nicht unterstützte Werte wie undefined oder eine Funktion dazu, dass stringify den Wert undefined statt JSON-Text zurückgibt.

Ein Date schreibt seine ISO-Zeichenkette in UTC über toJSON. Gewöhnliche Map- und Set-Einträge werden nicht geschrieben, sodass beide Sammlungsarten zu {} werden. Wandle Set-Werte in ein Array und Map-Einträge in Paare oder ein Objekt mit Zeichenkettenschlüsseln um, bevor du sie schreibst.

Eine zirkuläre Referenz und ein gewöhnlicher BigInt wie 10n verursachen einen TypeError. Gemeinsam genutzte Referenzen, die keinen Zyklus bilden, lassen sich serialisieren, aber JSON erhält ihre gemeinsame Identität nicht.

Daten mit einem replacer-Parameter auswählen
const user = { name: "Rae", email: "rae@example.com", password: "x9!k", age: 31 };
JSON.stringify(user, ["name", "email"]);
// '{"name":"Rae","email":"rae@example.com"}'

Ein replacer-Array wählt Eigenschaftsnamen aus. Eine replacer-Funktion transformiert Werte bei ihrer Verarbeitung, beginnend mit der gesamten Eingabe unter dem Schlüssel "":

JSON.stringify(user, (key, value) =>
  key === "password" ? undefined : value
);

Die Rückgabe von undefined lässt eine Objekteigenschaft weg, macht eine Arrayposition zu null oder führt bei der Rückgabe für den Wurzelwert zu einem Gesamtergebnis von undefined. Gib für Daten, die du behalten möchtest, den unveränderten Wert zurück.

Die toJSON()-Methode eines Objekts kann dessen Darstellung wählen. Für { celsius: 21, toJSON() { return { c: this.celsius }; } } schreibt die Serialisierung '{"c":21}'.

Erstelle JSON nicht selbst durch das Verbinden von Zeichenketten in Anführungszeichen: Eingebettete Anführungszeichen oder Zeilenumbrüche können seine Syntax beschädigen. Wandle auch bereits serialisierten Text nicht in der Erwartung erneut in eine JSON-Zeichenkette um, eine Objektdarstellung zu erhalten. Die Serialisierung von '{"a":1}' kodiert eine Zeichenkette; einmaliges Parsen dieses Ergebnisses gibt eine Zeichenkette zurück, kein Objekt.

Wichtige Erkenntnisse

  • JSON.stringify gibt normalerweise JSON-Text zurück; nicht unterstützte Werte auf oberster Ebene können undefined ergeben.
  • Nicht unterstützte Objekteigenschaften verschwinden, während nicht unterstützte Arrayelemente zu null werden.
  • Datumswerte werden zu Zeichenketten; Map und Set benötigen eine ausdrückliche Umwandlung.
  • Zirkuläre Strukturen und gewöhnliche BigInts lösen einen TypeError aus.
  • replacer-Parameter und toJSON steuern die geschriebene Darstellung.
  • Die erneute Serialisierung von JSON-Text kodiert eine Zeichenkette, nicht das darin enthaltene Objekt.

5.3 Wandle JSON-Text mit JSON.parse in Werte um

JSON.parse liest JSON-Text und gibt den Wert zurück, den er beschreibt. Das Parsen prüft die Syntax des Textes; ob das Ergebnis zu deinem Programm passt, musst du gesondert prüfen.

Den Wert lesen und dann seine Felder prüfen
const data = JSON.parse('{"city":"Lima","tempC":19.5}');
data.tempC + 1; // 20.5

Die äußeren einfachen Anführungszeichen begrenzen eine JavaScript-Zeichenkette. Die doppelten Anführungszeichen darin gehören zu JSON. Das Parsen erstellt ein einfaches Objekt mit einer numerischen tempC-Eigenschaft. Ein Text, der ein Array beschreibt, erzeugt ein Array; primitive JSON-Texte erzeugen ihre entsprechenden primitiven Werte.

Daten, die bereits ein Objekt sind, müssen nicht geparst werden. JSON.parse({ a: 1 }) wandelt dieses Argument zuerst in "[object Object]" um und löst dann einen SyntaxError aus. Auch JSON.parse(undefined) schlägt fehl, weil "undefined" kein gültiger JSON-Text ist.

Ungültigen Text behandeln
function safeParse(text, fallback) {
  try {
    return JSON.parse(text);
  } catch (error) {
    return fallback;
  }
}
safeParse("{ok:true}", null); // null

Fehlerhafte Eingaben, darunter eine leere Zeichenkette, JSON-Zeichenketten in einfachen Anführungszeichen, Schlüssel ohne Anführungszeichen und abschließende Kommas, lösen einen SyntaxError aus. Wird dieser Fehler abgefangen, erhält das Programm eine gezielte Rückfalllösung, statt angehalten zu werden. Auch ein erfolgreich geparstes null ist möglich. Entscheide daher, wie der Aufrufer eine Rückfalllösung von gültigen Daten unterscheiden soll, wenn dieser Unterschied wichtig ist.

Ausgewählte Werte mit einer Reviver-Funktion wiederherstellen

Ein als Text gespeichertes Datum kommt als Zeichenkette zurück. Ein Array aus Schlüssel-Wert-Paaren bleibt ein Array, bis new Map(pairs) es in eine Map umwandelt. Beim Schreiben weggelassene Funktionen lassen sich aus dem verbleibenden Text nicht wiederherstellen.

const text = '{"title":"Dentist","due":"2026-03-01T09:00:00.000Z"}';
const event = JSON.parse(text, (key, value) =>
  key === "due" ? new Date(value) : value
);

Die Reviver-Funktion besucht innere Werte vor den Werten, die sie enthalten, und endet mit dem gesamten Ergebnis unter dem Schlüssel "". Die Rückgabe eines Werts ersetzt den aktuellen Wert. Die Rückgabe von undefined entfernt diese Eigenschaft; wird es für den Wurzelwert zurückgegeben, wird das gesamte Parsergebnis zu undefined. Wird return value für andere Schlüssel vergessen, können daher Daten gelöscht werden, die du behalten wolltest.

Struktur prüfen und einen Roundtrip planen

Gültiges JSON kann dennoch die falschen Typen enthalten. Das Parsen von '{"temp":"19"}' lässt eine Zeichenkette zurück, sodass data.temp + 1 durch Verkettung "191" ergeben würde. Prüfe vor dem Rechnen Pflichtfelder und Typen, etwa mit typeof data?.temp === "number". Wandle nur dann mit Number um, wenn das vorgesehene Format eine numerische Zeichenkette erlaubt; optionale Verkettung und ?? können Felder behandeln, die fehlen dürfen.

Für const settings = { theme: "dark", volume: 0.8, recent: ["a.txt"] }; erzeugt die Serialisierung 48 Zeichen JSON-Text. Das Parsen stellt dieselben Felddaten wieder her, aber loaded === settings ist false, weil das Parsen neue Objekte erstellt. Ein Date kommt als Zeichenkette zurück, eine Objekteigenschaft mit dem Wert undefined verschwindet und ein nicht umgewandeltes Set kommt als {} zurück. Wandle besondere Werte vor dem Schreiben um und stelle ihre vorgesehenen Typen nach dem Lesen wieder her.

Wichtige Erkenntnisse

  • JSON.parse liest Text und löst bei fehlerhaftem JSON einen SyntaxError aus.
  • Erfolgreiches Parsen prüft weder die erforderlichen Felder noch ihre Typen.
  • Eine Reviver-Funktion besucht Kindwerte zuerst und muss Werte zurückgeben, die du behalten möchtest.
  • JSON-Roundtrips erstellen neue Objekte und erhalten nur darstellbare Daten.
  • Stelle Sammlungs- und Datumstypen nach dem Parsen ausdrücklich wieder her.

Objekte und JSON in JavaScript: Beispiele

5 Interaktive Lektionen

1

Verfolge einen Sendungsdatensatz

16 Schritte
Erstelle, untersuche und kopiere einen verschachtelten Datensatz und verfolge dabei, welche Werte gemeinsam genutzt werden.
  1. 1
    EinführungErstelle einen Datensatz, den du untersuchen kannst

    Eine Sendung umfasst eine ID, ein Ziel und Paketdatensätze. Du erstellst sie, untersuchst ihre Felder und verfolgst gemeinsam genutzte und kopierte Daten. Zwei Namen können dieselbe Referenz auf einen Datensatz enthalten, und eine flache Kopie nutzt verschachtelte Ebenen weiterhin gemeinsam. Eine Aktualisierung kann daher Daten erreichen, die du getrennt halten wolltest.

    Die Sendungsbeispiele werden über die Folien hinweg fortgeführt, sofern ein Schritt nicht ausdrücklich ein separates Objekt erstellt.

  2. 2
    BeispielErstelle die Sendung
    const shipment = {
      id: "s12",
      destination: "Porto",
      delayMin: 0
    };
    

    Das Literal erstellt drei Eigenschaften. Die Verspätung wird in Minuten gemessen; auch null ist ein gültiger Wert. shipment.destination liest "Porto". Const erlaubt die Aktualisierung von Eigenschaften.

  3. 3
    BeispielWähle ein Feld zur Laufzeit des Programms
    const field = "destination";
    shipment[field] = "Braga";
    shipment.checked = true;
    

    Der Zugriff mit eckigen Klammern wertet field aus und aktualisiert die Eigenschaft destination. Die Zuweisung fügt außerdem checked hinzu, weil die Eigenschaft zuvor nicht existierte. Die Sendung hat weiterhin dieselbe Identität; keine der beiden Operationen ersetzt das äußere Objekt. shipment.field würde stattdessen eine separate Eigenschaft mit dem wörtlichen Namen "field" erstellen.

  4. 4
    HerausforderungLies einen berechneten Namen

    Was liest shipment[field] jetzt und besitzt die Sendung eine eigene Eigenschaft field?

    ---reveal---

    Der Ausdruck liest "Braga". Die Variable field enthält den Schlüssel "destination", sodass sowohl die Aktualisierung als auch der Lesezugriff diese Eigenschaft erreichen. Object.hasOwn(shipment, "field") ist false, weil keine Eigenschaft mit dem wörtlichen Namen field erstellt wurde. Eine Variable, mit der eine Eigenschaft ausgewählt wird, wird nicht selbst Teil des Datensatzes.

  5. 5
    ErklärungPrüfe null, ohne den Wert zu verlieren

    shipment.delayMin ist null, sodass eine Bedingung, die den Wahrheitswert prüft, ihren Anweisungsblock überspringt. Die Eigenschaft existiert trotzdem.

    Object.hasOwn(shipment, "delayMin") gibt true zurück. Verwende für gespeicherte Felder eine Prüfung auf eigene Eigenschaften; der Operator in berücksichtigt auch geerbte Eigenschaften.

  6. 6
    BeispielLies die Einträge
    const pairs = Object.entries(shipment);
    const count = Object.keys(shipment).length;
    

    Es gibt nun vier eigene aufzählbare Felder mit Zeichenkettenschlüsseln, darunter checked. Entries liefert für jedes ein [key, value]-Paar. Du kannst sie mit for (const [key, value] of pairs) durchlaufen, um beide Teile zu untersuchen. Eine direkte for...of-Schleife über das einfache shipment-Objekt würde einen Fehler auslösen, weil dieses Objekt nicht iterierbar ist.

  7. 7
    HerausforderungUnterscheide Existenz und Wert

    Angenommen, shipment.note = undefined; wird hinzugefügt. Was geben shipment.note und Object.hasOwn(shipment, "note") zurück?

    ---reveal---

    Sie geben undefined und true zurück. Die Zuweisung erstellt die Eigenschaft, obwohl ihr Wert undefined ist. Würde die Eigenschaft gelöscht, änderte sich das Ergebnis der Existenzprüfung zu false, während ein späterer Lesezugriff weiterhin undefined liefern würde. Der Wert allein kann diese beiden Situationen nicht unterscheiden.

  8. 8
    AnalogieVerfolge zwei Wege zu einem Datensatz

    Eine Referenz funktioniert wie ein Weg zu einem Datensatz: Wird der Weg kopiert, entsteht eine weitere Möglichkeit, dasselbe Ziel zu erreichen. Es wird kein zweiter Datensatz erstellt.

    const alias = shipment;
    alias.checked = false;
    

    shipment.checked ist nun ebenfalls false. Beide Variablennamen führen zu einem Objekt, daher ist alias === shipment gleich true. Übereinstimmende Referenzen erklären die gemeinsame Aktualisierung; zwischen zwei Kopien wurde kein Synchronisierungsschritt ausgeführt.

  9. 9
    BeispielFüge Daten hinzu, die eine flache Kopie gemeinsam nutzt
    shipment.packages = [{ massG: 450 }, { massG: 700 }];
    const shallow = { ...shipment };
    shallow.destination = "Faro";
    shallow.packages[0].massG = 500;
    

    Der neue äußere Datensatz hat ein eigenes Ziel, daher bleibt shipment.destination gleich Braga. Sein packages-Wert ist dieselbe Arrayreferenz wie zuvor. Über diesen gemeinsam genutzten Pfad wird auch die Masse des ersten Pakets in der ursprünglichen Sendung auf 500 geändert.

  10. 10
    BeispielErstelle eine unterstützte tiefe Kopie
    const deep = structuredClone(shipment);
    deep.packages[0].massG = 600;
    

    Das erste ursprüngliche Paket bleibt bei 500 g, weil die tiefe Kopie ein eigenes verschachteltes Array und eigene Paketobjekte hat. Dieser Datensatz enthält nur unterstützte Daten. Enthielte er eine Eigenschaft, deren Wert eine Funktion ist, würde structuredClone einen DataCloneError auslösen, statt diese Methode unbemerkt wegzulassen.

  11. 11
    HerausforderungBestimme die Wirkung des Einfrierens

    Führe diese Anweisungen aus. Löst die verschachtelte Zuweisung einen Fehler aus und wie groß ist danach die zweite Masse?

    Object.freeze(shipment);
    shipment.packages[1].massG = 750;
    

    ---reveal---

    Sie gelingt und setzt die Masse auf 750. Das Einfrieren von shipment schützt dessen eigene Eigenschaften, aber nicht das referenzierte Array oder dessen Datensätze. Eine Neuzuweisung von shipment.destination würde im strikten Modus einen TypeError auslösen; diese verschachtelte Zuweisung erreicht ein anderes, nicht eingefrorenes Objekt.

  12. 12
    BeispielBerechne die aktuelle Gesamtmasse
    const totalG = shipment.packages.reduce(
      (sum, pack) => sum + pack.massG, 0
    );
    

    Nach den vorherigen Aktualisierungen enthält die ursprüngliche Sendung die Massen 500 und 750 g. Reduce beginnt bei null, addiert 500 und dann 750 und ergibt 1250. Die Gesamtmasse wird aus den aktuellen Paketen berechnet. Wenn sich deren Massen später ändern, führe die Berechnung erneut aus; diese gespeicherte Zahl berechnet sich nicht selbst neu.

  13. 13
    TippSichere einen optionalen Pfad ab
    const contactName = shipment.contact?.name ?? "Unassigned";
    

    Im Datensatz gibt es keine Eigenschaft contact, daher ergibt die optionale Verkettung undefined und die Rückfalllösung liefert "Unassigned". Dieser Pfad darf fehlen. Halte Pflichtfelder für die Validierung sichtbar, statt alle Fehler unbemerkt durch Standardwerte zu ersetzen. Die Rückfalllösung für null und undefined behält außerdem einen absichtlich leeren Namen bei, anders als eine Rückfalllösung mit logischem ODER.

  14. 14
    HerausforderungBehalte eine gültige null bei

    Was geben shipment.delayMin ?? 10 und shipment.delayMin || 10 zurück?

    ---reveal---

    Der erste Ausdruck gibt 0 zurück; der zweite gibt 10 zurück. Der Nullish-Coalescing-Operator ersetzt nur null oder undefined, während das logische ODER jeden Falsy-Wert ersetzt. Für diese Sendung ist eine Verspätung von null Minuten erfasst. Würde sie als fehlend behandelt, entstünde eine Verspätung, die in den gespeicherten Daten nie angegeben wurde.

  15. 15
    HerausforderungKombiniere eine Kopie mit einer optionalen Aktualisierung

    Mit const next = { ...shipment }; wird ein neuer Datensatz erstellt, danach folgt next.packages[0].massG = 520;. Was geschieht mit der ersten Masse von shipment und ist next dasselbe äußere Objekt?

    ---reveal---

    Die ursprüngliche Masse wird zu 520, weil das verschachtelte Array gemeinsam genutzt wird. next === shipment ist false, weil Spread ein neues äußeres Objekt erstellt hat. Das Kopieren des äußeren Datensatzes trennt Zuweisungen an seine eigenen Eigenschaften, macht aber nicht einen gesamten verschachtelten Pfad unabhängig.

  16. 16
    ZusammenfassungWähle die passende Prüfung für die Aufgabe

    Wähle eine Eigenschaft anhand eines wörtlichen oder berechneten Schlüssels und unterscheide Existenz vom Wahrheitswert. Verfolge vor einer Aktualisierung, ob ihr Pfad gemeinsam genutzte Daten erreicht.

    Kopiere verschachtelte Ebenen, die unabhängig sein müssen. Berechne abgeleitete Summen erneut, nachdem sich ihre Eingabewerte geändert haben.

2

Halte eine Aktion mit ihrem Objekt verbunden

12 Schritte
Verfolge Methodenaufrufe, übernommenen Kontext und Callbacks anhand eines kleinen Zählers.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungVerfolge die Weitergabe einer Aktion
  2. 2
    BeispielErstelle und rufe eine Aktion auf
  3. 3
    HerausforderungLies die Aktion, ohne sie auszuführen
  4. 4
    BeispielEntleihe die reguläre Funktion
  5. 5
    HerausforderungLöse die entliehene Methode ab
  6. 6
    KernaussageSetze eine Pfeilfunktion in die Methode
  7. 7
    BeispielUmschließe den benötigten Aufruf
  8. 8
    BeispielBinde einen Callback einmalig
  9. 9
    HerausforderungWähle zwischen sofortiger und späterer Ausführung
  10. 10
    TippGib einer bestehenden Bindung Vorrang
  11. 11
    HerausforderungVerfolge eine gebundene Methode über ein anderes Objekt
  12. 12
    ZusammenfassungLies die Aufrufform
3

Entpacke Optionen und erstelle einen aktualisierten Datensatz

14 Schritte
Lies Muster von außen nach innen und kopiere dann nur die Ebenen, die sich ändern müssen.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungLies kompakte Syntax in kleinen Schritten
  2. 2
    BeispielWähle Felder aus und benenne sie um
  3. 3
    BeispielGehe in ein verschachteltes Muster
  4. 4
    HerausforderungLies ein umbenanntes verschachteltes Feld
  5. 5
    HerausforderungUnterscheide null von einem fehlenden Wert
  6. 6
    BeispielEntpacke einen zurückgegebenen Wertebereich
  7. 7
    BeispielSammle den Rest in einem eigenen Array
  8. 8
    HerausforderungVertausche Werte, bevor du sie verwendest
  9. 9
    BeispielFühre Standardwerte mit überschreibenden Werten zusammen
  10. 10
    BeispielKopiere die verschachtelte Ebene, die sich ändert
  11. 11
    VerbindungEntferne ein Feld aus dem neuen Datensatz
  12. 12
    HerausforderungWähle eine unabhängige Aktualisierung
  13. 13
    HerausforderungVerbinde Eintragsmuster mit Spread
  14. 14
    ZusammenfassungErkenne die Aufgabe, bevor du Werte verfolgst
4

Verfolge Zählwerte und eindeutige Zugehörigkeit

11 Schritte
Verwende Map für wechselnde Werte mit Schlüsseln und Set für die Zugehörigkeit und vergleiche anschließend Sammlungen.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungWähle, was sich die Sammlung merken muss
  2. 2
    BeispielErstelle Zählwerte mit Map-Methoden
  3. 3
    TippHalte Einträge und Eigenschaften getrennt
  4. 4
    HerausforderungHalte Schlüsseltypen auseinander
  5. 5
    BeispielVerwende einen Objektschlüssel erneut
  6. 6
    BeispielSammle eindeutige Bezeichnungen
  7. 7
    HerausforderungEntscheide, ob Datensätze Duplikate sind
  8. 8
    BeispielFinde die gemeinsamen und fehlenden Bezeichnungen
  9. 9
    KernaussageÄndere die Frage nach der Zugehörigkeit
  10. 10
    HerausforderungVerbinde Zählwerte mit der Zugehörigkeit
  11. 11
    ZusammenfassungStimme die Struktur auf die Operation ab
5

Schreibe, lies und prüfe JSON-Daten

14 Schritte
Plane eine JSON-geeignete Darstellung, behandle ungültigen Text und stelle die vorgesehenen Typen wieder her.

Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.

  1. 1
    EinführungPlane beide Richtungen der Umwandlung
  2. 2
    ErklärungLies Text als Text
  3. 3
    HerausforderungBehebe ein Syntaxproblem
  4. 4
    BeispielUntersuche die aktuellen Einstellungen
  5. 5
    BeispielWandle die Sammlung vor dem Schreiben um
  6. 6
    TippLass den Serialisierer Zeichenketten maskieren
  7. 7
    HerausforderungBestimme das Ergebnis für ein nicht unterstütztes Arrayelement
  8. 8
    BeispielParse und stelle die Zugehörigkeitsprüfung wieder her
  9. 9
    BeispielBehandle fehlerhaften Text gezielt
  10. 10
    HerausforderungPrüfe einen gültigen, aber ungeeigneten Wert
  11. 11
    ErklärungStelle ein Feld mit einer Reviver-Funktion wieder her
  12. 12
    HerausforderungErhalte die Unterscheidung von Map-Schlüsseln
  13. 13
    VerbindungHalte Klonen und Austausch auseinander
  14. 14
    ZusammenfassungPrüfe Syntax, Struktur und Darstellung

Objekte und JSON in JavaScript: Übungsaufgaben

50 Übungsfragen in 5 Sets

Set 1: Lies Datensätze und verfolge Werte10 Übungsfragen

Frage 1 von 10

Was gibt sensor[field] zurück?

const sensor = { tempC: 16, field: "room" };
const field = "tempC";
  1. "room"
  2. 16
  3. "tempC"
  4. undefined
Antwort zeigenAntwort ausblenden
Antwort: B
Der Zugriff mit eckigen Klammern verwendet den Wert von field, "tempC", um die Eigenschaft mit dem Wert 16 auszuwählen. Der Zugriff mit Punkt in sensor.field würde stattdessen die wörtliche Eigenschaft field lesen und "room" zurückgeben.

Frage 2 von 10

Was gibt Object.hasOwn(record, "enabled") zurück?

const record = { enabled: false };
  1. false
  2. undefined
  3. null
  4. true
Antwort zeigenAntwort ausblenden
Antwort: D
Der Datensatz besitzt enabled als eigene Eigenschaft, daher ergibt die Prüfung true. Ihr gespeicherter Wert false würde eine Prüfung des Wahrheitswerts nicht bestehen, macht die Eigenschaft aber nicht zu einer fehlenden Eigenschaft.

Frage 3 von 10

Welche Werte haben record.region und record.key?

const key = "region";
const record = { [key]: "east" };
record[key] = "west";
  1. "west" und undefined
  2. "east" und "west"
  3. undefined und "west"
  4. "west" und "east"
Antwort zeigenAntwort ausblenden
Antwort: A
Der berechnete Schlüssel erstellt region und die Zuweisung mit eckigen Klammern aktualisiert den Wert auf "west". Eine Eigenschaft mit dem wörtlichen Namen key wird nicht erstellt, daher gibt das Lesen von record.key undefined zurück.

Frage 4 von 10

Welchen Wert hat meter.value nach diesem Aufruf?

const meter = {
  value: 7,
  add() { this.value += 3; }
};
meter.add();
  1. 7
  2. 3
  3. 10
  4. undefined
Antwort zeigenAntwort ausblenden
Antwort: C
Der Methodenaufruf macht meter zum Empfängerobjekt und ändert value von 7 auf 10. Die Rückgabe von undefined durch eine Methode ohne return macht ihre Aktualisierung der Eigenschaft nicht rückgängig.

Frage 5 von 10

Was gibt right.read() zurück?

const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
  1. "Ivo"
  2. "Nia"
  3. undefined
  4. Einen TypeError
Antwort zeigenAntwort ausblenden
Antwort: B
Die reguläre Funktion wird über right aufgerufen, daher ist this gleich right und der zurückgegebene Name ist "Nia". Die Funktion wurde ursprünglich in left geschrieben, doch diese Stelle bindet ihr Empfängerobjekt nicht. Die Rückgabe von "Ivo" würde den ursprünglichen Speicherort mit dem beim aktuellen Aufruf verwendeten Objekt verwechseln.

Frage 6 von 10

Welche Werte haben title und score nach der Destrukturierung?

const { name: title, score = 8 } = { name: "Reef", score: null };
  1. "Reef" und null
  2. "Reef" und 8
  3. undefined und 8
  4. undefined und null
Antwort zeigenAntwort ausblenden
Antwort: A
Das Muster liest die Eigenschaft name in die lokale Variable title. Sein Standardwert für score wird nur bei undefined verwendet, daher bleibt das ausdrücklich angegebene null erhalten. Würde null durch 8 ersetzt, würde die weiter gefasste Regel für Standardwerte bei null und undefined auf die Destrukturierung angewendet, die nur bei undefined greift.

Frage 7 von 10

Welchen Wert erhält third?

const [, , third] = [4, 9, 12, 18];
  1. 4
  2. 9
  3. 12
  4. 18
Antwort zeigenAntwort ausblenden
Antwort: C
Die beiden leeren Positionen überspringen 4 und 9, sodass 12 für third bleibt. Die Auswahl von 9 würde nur eine Position überspringen; der Variablenname selbst wählt keinen Index aus.

Frage 8 von 10

Welche Werte haben m.size und m.get(2)?

const m = new Map([[2, "number"], ["2", "text"]]);
  1. 1 und "text"
  2. 2 und "text"
  3. 1 und "number"
  4. 2 und "number"
Antwort zeigenAntwort ausblenden
Antwort: D
Eine Map erhält die Typen der Schlüssel, sodass die numerische 2 und die Zeichenkette "2" zwei getrennte Einträge belegen. Die Abfrage mit der numerischen 2 gibt "number" zurück. Eine Größe von 1 ergäbe sich, wenn beide Schlüssel als dieselbe Zeichenkette behandelt würden, wie es bei diesen Namen als gewöhnlichen Objekteigenschaften der Fall ist.

Frage 9 von 10

Eine Datendatei muss die exakten ID-Ziffern 9007199254740997 erhalten und sich als JSON parsen lassen. Welcher Datensatztext erfüllt beide Anforderungen?
  1. {"id":9007199254740997,"active":true}
  2. {id:"9007199254740997",active:true}
  3. {"id":"9007199254740997","active":true}
  4. {"id":'9007199254740997',"active":true}
Antwort zeigenAntwort ausblenden
Antwort: C
Schlüssel in doppelten Anführungszeichen und kleingeschriebenes true machen den Datensatz zu gültigem JSON, und eine Zeichenkette erhält jede ID-Ziffer. Die große Ganzzahl ohne Anführungszeichen wird beim Parsen in JavaScript gerundet, obwohl ihre Syntax gültig ist. Schlüssel ohne Anführungszeichen oder einfache Anführungszeichen um die ID bestehen die JSON-Syntaxprüfung nicht.

Frage 10 von 10

Welcher Text wird zurückgegeben?

JSON.stringify({
  note: undefined,
  values: [undefined, NaN],
  ok: false
});
  1. '{"values":[null,null],"ok":false}'
  2. '{"note":null,"values":[null,null],"ok":false}'
  3. '{"values":[],"ok":false}'
  4. '{"values":[null,null]}'
Antwort zeigenAntwort ausblenden
Antwort: A
Die Objekteigenschaft mit dem Wert undefined wird weggelassen, während undefined in einem Array zu null wird. Auch NaN wird zu null und der gültige boolesche Wert false bleibt erhalten. Würde note als null erhalten bleiben, wäre die Arrayregel fälschlich auf eine Objekteigenschaft angewendet worden; das Löschen von Arraypositionen würde deren Struktur ändern.
Set 2: Wende Muster an und erhalte Empfängerobjekte10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Was gibt trip.host?.name ?? "Guest" zurück?

const trip = { host: null };
  1. null
  2. undefined
  3. "Guest"
  4. Einen TypeError
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Was sind die endgültigen Werte von a.level und a === b?

const a = { level: 2 };
const b = a;
b.level = 5;
  1. 5 und true
  2. 2 und false
  3. 5 und false
  4. 2 und true
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Welche Werte haben source.mode und source.layout.width danach?

const source = { mode: "day", layout: { width: 40 } };
const copy = { ...source };
copy.mode = "night";
copy.layout.width = 60;
  1. "night" und 60
  2. "day" und 40
  3. "night" und 40
  4. "day" und 60
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Welche Funktion kann an map übergeben werden, sodass jeder Aufruf tally aktualisiert?

const tally = { n: 0, tick() { return ++this.n; } };
const result = ["x", "y"].map(/* callback */);
  1. tally.tick
  2. () => tally.tick()
  3. tally.tick()
  4. () => tally.tick
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Dieser Code läuft auf der obersten Modulebene. Was geschieht beim Aufruf von card.read()?

const card = { title: "Basin", read: () => this.title };
  1. Er löst einen TypeError aus.
  2. Er gibt "Basin" zurück.
  3. Er gibt undefined zurück.
  4. Er löst einen ReferenceError aus.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Welche Werte haben next.mode und base.panel.width nach next.panel.width = 90?

const base = { mode: "wide", panel: { width: 50 } };
const next = { mode: "small", ...base, panel: { ...base.panel } };
  1. "small" und 50
  2. "wide" und 90
  3. "small" und 90
  4. "wide" und 50
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Welchen Wert erhält size?

const { size = 6 } = {};
  1. undefined
  2. 6
  3. null
  4. 0
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Welches Array erzeugt dieser Ausdruck?

[...new Set(["red", "blue", "red", "green", "blue"])];
  1. ["blue", "green", "red"]
  2. ["red", "green", "blue"]
  3. ["red", "blue", "green"]
  4. ["red", "blue", "red", "green", "blue"]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Was ist der endgültige Wert von loaded?

const loaded = JSON.parse('{"count":4,"tag":"a"}', (key, value) => {
  if (key === "count") return value * 2;
});
  1. undefined
  2. { count: 8, tag: "a" }
  3. { count: 8 }
  4. {}
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Was geschieht, wenn dieser Text geparst wird?

JSON.parse('{"mode":"fast","mode":"slow"}');
  1. Es wird { mode: "fast" } zurückgegeben.
  2. Es wird { mode: "slow" } zurückgegeben.
  3. Es wird ein SyntaxError ausgelöst.
  4. Es wird { mode: ["fast", "slow"] } zurückgegeben.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 3: Transformiere Sammlungen und stelle Daten wieder her10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Welches Objekt erstellt der Ausdruck?

Object.fromEntries(
  Object.entries({ north: 3, south: 5 })
    .map(([key, value]) => [key, value + 2])
);
  1. { north: 5, south: 7 }
  2. { north: 3, south: 5 }
  3. { north: 6, south: 10 }
  4. { 5: "north", 7: "south" }
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Was gibt options.limit ?? 12 zurück?

const options = { limit: 0 };
  1. 12
  2. undefined
  3. 0
  4. null
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Was muss add zurückgeben, damit basket.add("pear").add("fig") zweimal denselben Warenkorb verwendet?

const basket = {
  items: [],
  add(item) { this.items.push(item); /* return here */ }
};
  1. this.items
  2. item
  3. this.items.length
  4. this
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Welches Array wird in diesem Modul zurückgegeben?

function scale(n) { return this.factor * n; }
const twice = scale.bind({ factor: 2 });
const obj = { factor: 9, twice };
[obj.twice(3), twice.call({ factor: 5 }, 4)];
  1. [27, 20]
  2. [6, 8]
  3. [6, 20]
  4. [27, 8]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Was wird zurückgegeben?

function combine(first, ...others) {
  return [first, others.length];
}
combine(...[7, 3, 8, 2]);
  1. [7, 4]
  2. [[7, 3, 8, 2], 0]
  3. [7, 3]
  4. [7, 2]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Welche Werte haben items[0].done, next[1] === items[1] und next === items?

const items = [{ id: 4, done: false }, { id: 9, done: false }];
const next = items.map(item =>
  item.id === 4 ? { ...item, done: true } : item
);
  1. true, true, false
  2. false, true, false
  3. false, false, false
  4. false, true, true
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Warum ist lookup.get({ code: 8 }) gleich undefined?

const key = { code: 8 };
const lookup = new Map([[key, "ready"]]);
  1. Die Abfrage verwendet eine andere Objektreferenz.
  2. Map wandelt beide Schlüssel in verschiedene Zeichenketten um.
  3. Map ignoriert Objektschlüssel beim Erstellen von Einträgen.
  4. Der Schlüssel muss zuerst in JSON-Text umgewandelt werden.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Welche Größen haben a.difference(b) und a.symmetricDifference(b)?

const a = new Set([2, 4, 6]);
const b = new Set([4, 8]);
  1. 1 und 1
  2. 3 und 2
  3. 2 und 4
  4. 2 und 3
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Welchen Text erzeugt dies?

JSON.stringify({ label: "Arc", count: 3 }, ["label"]);
  1. '{"label":"Arc","count":3}'
  2. '{"label":"Arc"}'
  3. '["label"]'
  4. '{"label":"Arc","count":null}'
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Dieses Modul läuft ohne Reviver-Funktion. Welche Werte haben typeof loaded.due und loaded === original?

const original = { due: new Date("2026-07-12T00:00:00.000Z") };
const loaded = JSON.parse(JSON.stringify(original));
  1. "object" und false
  2. "string" und true
  3. "object" und true
  4. "string" und false
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 4: Untersuche Aktualisierungen und Aufrufe10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Welche Werte haben base.inner.n, clone.inner.n und copy.inner.n am Ende?

const base = { inner: { n: 2 } };
const copy = { ...base };
const clone = structuredClone(base);
Object.freeze(base);
copy.inner.n = 7;
clone.inner.n = 9;
  1. 2, 9, 7
  2. 9, 9, 9
  3. 2, 9, 2
  4. 7, 9, 7
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Welches Array gibt Object.keys(data) zurück?

const data = { z: 1, "10": 2, "02": 3, "2": 4, a: 5 };
  1. ["z", "10", "02", "2", "a"]
  2. ["2", "10", "z", "02", "a"]
  3. ["02", "2", "10", "z", "a"]
  4. ["2", "02", "10", "z", "a"]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Was ist totalG und ändert eine Änderung von heavy.massG auch load.items[1].massG?

const load = { items: [
  { massG: 120, qty: 2 },
  { massG: 300, qty: 1 }
] };
const heavy = load.items.find(x => x.massG > 200);
const totalG = load.items.reduce((s, x) => s + x.massG * x.qty, 0);
heavy.massG = 350;
  1. 540; ja, der Wert wird 350.
  2. 590; ja, der Wert wird 350.
  3. 540; nein, der Wert bleibt 300.
  4. 420; ja, der Wert wird 350.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Was gibt b.labels() in diesem Modul zurück?

const a = {
  prefix: "A",
  names: ["oak"],
  labels() { return this.names.map(n => this.prefix + n); }
};
const b = { prefix: "B", names: ["elm"], labels: a.labels };
  1. ["Aoak"]
  2. ["Aelm"]
  3. ["Belm"]
  4. Der Aufruf löst einen TypeError aus.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Was ist typeof box.open?

const box = { open() { return "opened"; } };
  1. "function"
  2. "string"
  3. "object"
  4. "undefined"
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Was geschieht, wenn read() und read({ prefs: null }) getrennt aufgerufen werden?

function read({ prefs: { theme = "light" } = {} } = {}) {
  return theme;
}
  1. Beide Aufrufe geben "light" zurück.
  2. Der erste gibt "light" zurück; der zweite löst TypeError aus.
  3. Der erste löst TypeError aus; der zweite gibt null zurück.
  4. Der erste gibt undefined zurück; der zweite gibt null zurück.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Was ist tail?

const [head, ...tail] = [6, 8, 11];
  1. [6, 8, 11]
  2. 8
  3. [11]
  4. [8, 11]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Welche Werte haben m.size und [...m.keys()]?

const m = new Map([["p", 1], ["q", 2]]);
m.set("p", 4);
m["r"] = 5;
m.delete("q");
m.set("q", 6);
  1. 3 und ["p", "r", "q"]
  2. 2 und ["q", "p"]
  3. 2 und ["p", "q"]
  4. 3 und ["p", "q", "r"]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Warum schlägt JSON.parse('{"depthM":+7}') fehl?
  1. JSON-Zahlen dürfen nicht mit einem Pluszeichen beginnen.
  2. JSON-Zahlen dürfen keine ganzen Zahlen sein.
  3. JSON-Eigenschaftsnamen dürfen keine Großbuchstaben enthalten.
  4. JSON-Objekte müssen auch einen Zeichenkettenwert enthalten.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Welche Werte haben result.count und result.total?

const result = JSON.parse('{"count":"6","total":12}',
  (key, value) => key === "count" ? Number(value) : value
);
result.total += result.count;
  1. "6" und "126"
  2. 6 und "126"
  3. 6 und 18
  4. undefined und NaN
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Set 5: Kombiniere Datenentscheidungen und Umwandlungsregeln10 Übungsfragen

Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.

Frage 1 von 10

Was ist Object.hasOwn(record, "old") nach diesen Anweisungen?

const record = { old: undefined };
delete record.old;
  1. true
  2. false
  3. undefined
  4. Der Aufruf löst TypeError aus.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 2 von 10

Welche Werte haben a === b, a.left === a.right und b.left === b.right?

const shared = { n: 1 };
const a = { left: shared, right: shared };
const b = JSON.parse(JSON.stringify(a));
  1. false, true, true
  2. true, true, true
  3. false, true, false
  4. false, false, false
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 3 von 10

Was gibt saved() zurück?

const maker = {
  n: 5,
  make() { return () => this.n; }
};
const other = { n: 8, make: maker.make };
const saved = other.make().bind({ n: 12 });
  1. 5
  2. 12
  3. undefined
  4. 8
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 4 von 10

Was gibt fixed.apply({ offset: 30 }, [4]) zurück?

function add(a, b) { return this.offset + a + b; }
const fixed = add.bind({ offset: 2 }, 7);
  1. 13
  2. 41
  3. 36
  4. NaN
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 5 von 10

Welche Werte haben a, b und rest?

let a = 3, b = 8;
[a, b] = [b, a];
const [, ...rest] = [a, b, 13];
  1. 8, 8, [8, 13]
  2. 8, 3, [8, 3, 13]
  3. 8, 3, [3, 13]
  4. 3, 8, [8, 13]
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 6 von 10

Was ist nach publicCopy.profile.name = "New" der Wert von source.profile.name und besitzt source weiterhin secret als eigene Eigenschaft?

const source = { secret: "s", profile: { name: "Old" } };
const { secret, ...publicCopy } = source;
  1. "Old"; ja.
  2. "New"; ja.
  3. "New"; nein.
  4. "Old"; nein.
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 7 von 10

Was ist der endgültige Wert von counts.get("moss")?

const counts = new Map();
for (const word of ["moss", "fern", "moss", "moss"]) {
  counts.set(word, (counts.get(word) ?? 0) + 1);
}
  1. 1
  2. 2
  3. 4
  4. 3
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 8 von 10

Welche Werte haben records.size und ids.size?

const x = { id: 7 };
const records = new Set([x, x, { id: 7 }]);
const ids = new Set([...records].map(r => r.id));
  1. 2 und 1
  2. 1 und 1
  3. 3 und 1
  4. 2 und 2
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 9 von 10

Was ist typeof JSON.parse(text)?

const text = JSON.stringify('{"x":3}');
  1. "string"
  2. "object"
  3. "number"
  4. "undefined"
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Frage 10 von 10

Eine Map muss den numerischen Schlüssel 3 und den Zeichenkettenschlüssel "3" mit den Werten "n" und "s" getrennt erhalten. Welches Paar von Umwandlungen erhält sie bei einem Roundtrip durch JSON?
  1. Schreiben mit JSON.stringify(Object.fromEntries(m)); lesen mit new Map(Object.entries(JSON.parse(text))).
  2. Schreiben mit JSON.stringify([...m]); lesen mit new Map(JSON.parse(text)).
  3. Schreiben mit JSON.stringify(m); lesen mit new Map(Object.entries(JSON.parse(text))).
  4. Schreiben mit JSON.stringify([...m.keys()]); lesen mit new Map(JSON.parse(text)).
Antwort zeigenAntwort ausblenden

Speichere diese Einheit, um diese Antwort zu sehen.

Hängst du bei deiner eigenen Aufgabe fest? Hausaufgabenhilfe

Schlüsselbegriffe

79 Schlüsselbegriffe, jeweils mit Definition

A

Abgeleiteter Wert
Ein abgeleiteter Wert wird aus anderen gespeicherten Daten berechnet, etwa eine Summe aus einzelnen Positionen, und kann bei separater Speicherung veralten.
Wird die Entfernung einer Route aus ihren Teilstrecken berechnet, bleibt das Ergebnis nach einer Änderung einer Teilstrecke konsistent.
apply
apply führt eine Funktion sofort mit einem ausdrücklich angegebenen this-Wert und einem Array aus, das ihre gewöhnlichen Argumente enthält.
format.apply(reading, ["m", 2]) übergibt dasselbe Empfängerobjekt und dieselben Werte wie format.call(reading, "m", 2).
Array-Destrukturierung
Die Array-Destrukturierung liest Werte von aufeinanderfolgenden Positionen eines iterierbaren Objekts in ein Muster mit eckigen Klammern.
const [low, high] = bounds; setzt voraus, dass bounds seinen kleineren Wert vor seinem größeren Wert bereitstellt.
Array-Restelement
Ein Array-Restelement sammelt übrige Werte in einem neuen Array und muss am Ende des Musters stehen.
const [leader, ...others] = names; trennt den ersten Namen von einem Array der übrigen Namen.
Arrayindexschlüssel
Ein Arrayindexschlüssel ist eine übliche Ganzzahl-Zeichenkette von 0 bis einschließlich 4294967294, die numerisch vor anderen eigenen Zeichenkettenschlüsseln angeordnet wird.
Der Schlüssel "3" steht in Object.keys vor "12"; "03" bleibt unter den gewöhnlichen Zeichenkettenschlüsseln.

B

Berechneter Eigenschaftsname
Ein berechneter Eigenschaftsname wertet einen Ausdruck in eckigen Klammern aus, um eine Eigenschaft in einem Literal zu benennen.
Mit const code = "es"; erstellt { [code]: "Hola" } eine Eigenschaft namens "es".
bind
bind gibt eine neue Funktion mit einem festen this-Wert und optional festgelegten ersten Argumenten zurück; die Ausführung erfolgt erst beim Aufruf der neuen Funktion.
Das Speichern von const next = meter.step.bind(meter); erstellt einen Callback, der meter als Empfängerobjekt behält.

C

call
call führt eine Funktion sofort mit einem ausdrücklich angegebenen this-Wert aus, gefolgt von einzeln übergebenen gewöhnlichen Argumenten.
format.call(reading, "m", 2) übergibt format das Empfängerobjekt reading und zwei separate Argumente.

D

Differenzmenge
Eine Differenzmenge enthält Werte aus einer ersten Sammlung, die in einer zweiten fehlen; das Vertauschen der Sammlungen kann daher das Ergebnis ändern.
active.difference(blocked) behält aktive Werte, die im Set blocked nicht vorkommen.

E

Eigene Eigenschaft
Eine eigene Eigenschaft gehört unmittelbar zu einem Objekt; eine Prüfung auf eigene Eigenschaften schließt daher keine durch Vererbung erreichten Eigenschaften ein.
Object.hasOwn({}, "toString") ist false, obwohl "toString" in {} true ist.
Eigenschaft
Eine Eigenschaft verbindet einen Objektschlüssel mit einem Wert, etwa Daten oder einer Funktion.
Die Eigenschaft active in { active: false } existiert, obwohl ihr Wert ein falscher boolescher Wert ist.
Eigenschaftskurzschreibweise
Eine Eigenschaft in Eigenschaftskurzschreibweise übernimmt ihren Namen und Wert von einer gleichnamigen Variablen.
Bei einer Variablen namens city erstellt das Literal { city } dasselbe Feld wie { city: city }.
Einfacher Funktionsaufruf im strikten Modus
Ein einfacher Funktionsaufruf im strikten Modus ruft eine strikte reguläre Funktion ohne Empfängerobjekt auf, sodass ihr this-Wert undefined ist.
Wird eine Methode als f herausgelöst und in einem Modul mit f() aufgerufen, kann sie fehlschlagen, wenn sie versucht, this.name zu lesen.
Einfügereihenfolge
Die Einfügereihenfolge ist die Folge, in der unterschiedliche Schlüssel oder Werte erstmals in eine Sammlung aufgenommen werden; sie bleibt beim Durchlaufen von Map und Set erhalten.
Die Aktualisierung eines Map-Eintrags behält seinen Platz bei; wird er gelöscht und der Schlüssel erneut eingefügt, steht er zuletzt.
Einrückungsargument
Das Einrückungsargument ist das dritte Argument von stringify und steuert die Leerzeichen oder eine kurze Zeichenkette zur Formatierung verschachtelten JSON-Texts.
Wird null als replacer-Parameter und 2 als drittes Argument übergeben, verwendet jede verschachtelte Ebene zwei Leerzeichen.
Empfängerobjekt
Ein Empfängerobjekt ist das Objekt, das bei einem regulären Methodenaufruf als this übergeben wird.
In account.describe() ist account das Empfängerobjekt, das die Methode zum Lesen seiner Felder verwendet.
Entliehene Methode
Eine entliehene Methode ist eine reguläre Funktion, die einem anderen Objekt entnommen und über ein neues Empfängerobjekt verwendet wird, ohne die Funktion selbst zu ändern.
Die Zuweisung b.read = a.read ermöglicht b.read(), die Daten von b zu verwenden, wenn die Funktion über this liest.
Escape-Sequenz
Eine Escape-Sequenz verwendet einen umgekehrten Schrägstrich und nachfolgende Zeichen, um ein Sonderzeichen oder eine UTF-16-Codeeinheit innerhalb einer JSON-Zeichenkette darzustellen.
Beim Serialisieren einer Nachricht mit Zeilenumbruch wird eine Escape-Sequenz geschrieben, statt einen tatsächlichen Zeilenumbruch in die Zeichenkette zu setzen.
Existenz einer Eigenschaft
Die Existenz einer Eigenschaft bedeutet, dass ein Schlüssel vorhanden ist, unabhängig davon, ob sein gespeicherter Wert truthy, falsy oder undefined ist.
Ein Datensatz mit count: 0 besitzt weiterhin eine Eigenschaft count; eine Prüfung dieses Werts als Bedingung erkennt sie nicht.

F

Flache Kopie
Eine flache Kopie erstellt ein neues äußeres Objekt oder Array und behält dabei Referenzen auf darin gespeicherte verschachtelte Objekte.
Eine Aktualisierung der verschachtelten Adresse eines kopierten Datensatzes kann auch die gemeinsam genutzte Adresse des ursprünglichen Datensatzes aktualisieren.

G

globalThis
globalThis bietet eine standardisierte Möglichkeit, auf das globale Objekt zu verweisen, das nicht strikte reguläre Funktionen bei einem einfachen Aufruf verwenden.
Das globale Objekt eines Browsers ist window, aber ein einfacher Funktionsaufruf im strikten Modus erhält dennoch undefined als this.

I

Iterierbares Objekt
Ein iterierbares Objekt liefert eine Folge von Werten für Operationen wie for...of oder Spread in Arrays.
Arrays, Zeichenketten, Maps und Sets lassen sich auf diese Weise entpacken; ein einfacher Datensatz nicht.

J

JSON
JSON ist ein sprachunabhängiges Textformat, das Objekte, Arrays, Zeichenketten, Zahlen, boolesche Werte und null mit strikter Syntax darstellt.
Der Text {"ready":true} beschreibt einen Datensatz, während true allein ebenfalls ein vollständiger gültiger JSON-Text ist.
JSON-Zeichenkette
Eine JSON-Zeichenkette besteht aus Textdaten, die durch doppelte Anführungszeichen begrenzt sind und Escape-Sequenzen für Zeichen wie Anführungszeichen und Zeilenumbrüche enthalten.
Ein Textwert mit einem Anführungszeichen benötigt innerhalb seiner umgebenden doppelten JSON-Anführungszeichen eine Escape-Sequenz.
JSON.parse
JSON.parse liest JSON-Text und gibt den darin dargestellten JavaScript-Wert zurück; bei fehlerhaftem Text löst es einen SyntaxError aus.
Das Parsen eines Datensatzes mit dem numerischen count-Wert 4 erlaubt Berechnungen, während count in Anführungszeichen eine Zeichenkette bleibt.
JSON.stringify
JSON.stringify serialisiert unterstützte JavaScript-Werte in JSON-Text und kann dabei Daten auswählen und eine lesbare Einrückung hinzufügen.
JSON.stringify(settings, null, 2) schreibt eine besser lesbare Form, ohne die dargestellten Einstellungen zu ändern.

K

Klammernotation
Die Klammernotation wertet den Ausdruck innerhalb eckiger Klammern aus, um einen Eigenschaftsschlüssel auszuwählen.
Mit const field = "heightM"; wählt person[field] die Größenmessung der Person aus.

L

Lexikalisches this
Lexikalisches this ist der umgebende this-Wert, den eine Pfeilfunktion an der Stelle ihrer Erstellung behält und den ein späteres Empfängerobjekt oder eine Bindung nicht beeinflusst.
Eine innerhalb einer laufenden Methode erstellte Pfeilfunktion kann während eines Array-Callbacks das Objekt dieser Methode behalten.
Losgelöste Methode
Eine losgelöste Methode ist eine Funktion, die aus einem Objekt gelesen und übergeben oder gespeichert wird, ohne das Objekt in ihrem späteren Aufrufausdruck beizubehalten.
const read = sensor.read; behält die Funktion, aber read() übergibt sensor nicht als Empfängerobjekt.

M

Map
Eine Map ist eine Sammlung von Schlüssel-Wert-Einträgen mit Schlüsseln beliebigen Typs, die die Reihenfolge des ersten Einfügens ihrer Schlüssel erhält.
Der numerische Schlüssel 5 und der Zeichenkettenschlüssel "5" bleiben getrennte Einträge, wenn sie in derselben Map gespeichert werden.
Map-Eintrag
Ein Map-Eintrag ordnet einem Schlüssel einen Wert zu und wird unabhängig von gewöhnlichen Objekteigenschaften mit Map-Methoden verwaltet.
stock.set("tea", 4) ändert einen Eintrag; stock["tea"] = 4 ändert eine gewöhnliche Eigenschaft.
Map.groupBy
Map.groupBy ist eine neuere Methode, die Elemente eines iterierbaren Objekts in Arrays innerhalb einer Map gruppiert und Typ und Identität der Gruppenschlüssel erhält.
Werden Datensätze nach einem gemeinsam genutzten Eigentümerobjekt gruppiert, kann dieselbe Eigentümerreferenz die zugehörige Gruppe abrufen.
Methode
Eine Methode ist eine Eigenschaft, deren Wert eine Funktion ist und die über ein Objekt aufgerufen wird.
Der Aufruf von tracker.advance() führt die Aktion von tracker aus, während das Lesen von tracker.advance eine Funktion zurückgibt.
Methodenkurzschreibweise
Die Methodenkurzschreibweise definiert eine reguläre Methode in einem Literal direkt durch ihren Namen, ihre Parameter und ihren Rumpf.
Das Mitglied reset() { this.n = 0; } definiert eine Aktion ohne separaten Doppelpunkt und ohne das Schlüsselwort function.
Methodenverkettung
Eine Methodenverkettung ruft eine Methode auf dem Wert auf, den der vorherige Aufruf zurückgegeben hat.
list.add("a").add("b") funktioniert, wenn der erste Aufruf ein Objekt mit der nächsten add-Methode zurückgibt.

N

Nullish-Coalescing-Operator
Der Nullish-Coalescing-Operator liefert nur dann eine Rückfalllösung, wenn sein linker Operand null oder undefined ist, und behält andere Falsy-Werte bei.
settings.volume ?? 1 behält eine ausdrücklich angegebene Lautstärke von null bei, während settings.volume || 1 sie ersetzt.

O

Object.freeze
Object.freeze verhindert das Hinzufügen, Löschen und Ändern eigener Eigenschaften eines Objekts, friert aber verschachtelte Objekte nicht ein.
In striktem Code löst eine Zuweisung an den Status auf oberster Ebene eines eingefrorenen Datensatzes einen TypeError aus.
Object.fromEntries
Object.fromEntries erstellt aus Schlüssel-Wert-Paaren ein Objekt und ist daher nach einer Transformation von Einträgen oder einer kompatiblen Map nützlich.
Durch Transformieren des Werts jedes Paars und erneutes Erstellen des Objekts lässt sich ein ganzer Datensatz von Messungen umwandeln.
Object.groupBy
Object.groupBy ist eine neuere Methode, die Elemente eines iterierbaren Objekts unter vom Callback ausgewählten Schlüsseln in Arrays eines Objekts ohne Prototyp gruppiert.
Das Gruppieren von Aufgaben nach Status ergibt ein Array für erledigte und ein weiteres für ausstehende Aufgaben.
Objekt-Rest
Objekt-Rest sammelt eigene aufzählbare Eigenschaften, die in einem Destrukturierungsmuster noch nicht benannt wurden, in einem neuen flachen Objekt.
const { password, ...publicRecord } = user; lässt user unverändert und schließt password aus der Kopie aus.
Objekt-Spread
Objekt-Spread kopiert eigene aufzählbare Eigenschaften in ein neues Literal, wobei spätere Vorkommen frühere Werte desselben Schlüssels überschreiben.
{ ...base, active: true } kopiert base und liefert danach den endgültigen Wert für active.
Objektdestrukturierung
Die Objektdestrukturierung liest ausgewählte Eigenschaften in Variablen, indem sie deren Namen zuordnet.
const { city, tempC } = reading; erstellt zwei lokale Variablen aus einem Wetterdatensatz.
Objektidentität
Die Objektidentität unterscheidet ein bestimmtes Objekt von jedem anderen Objekt, unabhängig von übereinstimmenden Feldwerten.
Zwei getrennt erstellte Datensätze mit id: 9 sind beim Vergleich mit === trotz übereinstimmender Daten ungleich.
Objektliteral
Ein Objektliteral erstellt ein Objekt direkt mit geschweiften Klammern und Schlüssel-Wert-Eigenschaften.
const reading = { tempC: 22 }; erstellt einen Datensatz mit einer Temperaturmessung.
Optionale Verkettung
Die optionale Verkettung bricht einen Eigenschaftszugriff, Indexzugriff oder Aufruf ab, wenn der geprüfte Wert null oder undefined ist, und ergibt undefined.
record.owner?.name erlaubt einen fehlenden owner, ohne zu versuchen, einen Namen aus undefined zu lesen.
Optionsobjekt
Ein Optionsobjekt übergibt einer Funktion benannte Einstellungen, statt sich auf Argumentpositionen zu stützen.
Eine Funktion, die { color, size } entgegennimmt, erlaubt Aufrufern anzugeben, was jede Einstellung bedeutet, ohne eine feste Reihenfolge einzuhalten.

P

Partielle Anwendung
Die partielle Anwendung legt einige Argumente jetzt fest, um eine Funktion zu erstellen, die bei einem späteren Aufruf die übrigen Argumente entgegennimmt.
multiply.bind(null, 4) erstellt eine Funktion, die ihr nächstes Argument mit vier multipliziert.
Pfeilfunktions-Wrapper
Ein Pfeilfunktions-Wrapper ist ein Pfeilfunktions-Callback, dessen Rumpf den vorgesehenen Methodenaufruf später ausführt und dessen Empfängerobjekt dabei ausdrücklich angibt.
Die Übergabe von () => counter.tick() an map sorgt dafür, dass jeder Callback-Aufruf tick über das Objekt counter aufruft.
Punktnotation
Die Punktnotation wählt den wörtlichen Eigenschaftsnamen nach einem Punkt aus.
profile.name wählt immer die Eigenschaft namens "name" aus, selbst wenn eine Variable namens name existiert.

R

Referenz
Eine Referenz verbindet eine Variable oder Eigenschaft mit einem Objekt und ermöglicht so mehreren Namen, denselben zugrunde liegenden Wert zu erreichen und zu ändern.
Die Zuweisung const backup = record; bietet einen weiteren Weg zu record, ohne dessen Felder zu kopieren.
replacer-Parameter
Ein replacer-Parameter ist das zweite stringify-Argument: ein Array aufzunehmender Eigenschaftsnamen oder eine Funktion, die besuchte Werte transformiert.
Die Rückgabe von undefined für eine private Objekteigenschaft lässt sie weg, während die Rückgabe des ursprünglichen Werts andere Daten erhält.
Restparameter
Ein Restparameter sammelt übrige Funktionsargumente in einem echten Array und muss der letzte Parameter in der Deklaration sein.
function total(...values) kann reduce auf values anwenden, auch wenn der Aufruf keine Argumente übergibt.
Reviver-Funktion
Eine Reviver-Funktion ist ein JSON.parse-Callback, der Werte nach ihren Kindwerten transformiert und sie mithilfe seiner Rückgabewerte ersetzt oder entfernt.
Eine Reviver-Funktion kann ein bekanntes Datumsfeld wiederherstellen und alle anderen Werte unverändert zurückgeben.
Roundtrip
Ein Roundtrip schreibt Daten in eine Darstellung und liest sie zurück; dabei bleiben nur die Informationen erhalten, die diese Darstellung ausdrücken kann.
Ein JSON-Roundtrip erstellt neue Objekte und gibt ein Date als Text zurück, sofern keine Umwandlung seinen Typ wiederherstellt.

S

Schlüssel-Wert-Paar
Ein Schlüssel-Wert-Paar ist eine Folge aus zwei Elementen, deren erster Wert ein Eigenschafts- oder Sammlungsschlüssel und deren zweiter Wert die zugehörigen Daten sind.
Object.entries({ lake: 5 }) erzeugt [["lake", 5]], bereit für eine Schleife über Schlüssel und Wert.
Schnittmenge
Eine Schnittmenge enthält nur die Werte, die in beiden Sammlungen vorhanden sind, und lässt Werte aus, die nur in einer von ihnen vorkommen.
Die Schnittmenge aktiver und genehmigter IDs liefert die IDs, die beide Zugehörigkeitsbedingungen erfüllen.
Serialisierung
Die Serialisierung wandelt Werte zur Laufzeit in eine Darstellung um, die gespeichert oder ausgetauscht werden kann, etwa in den von stringify erzeugten JSON-Text.
Ein Einstellungsobjekt muss serialisiert werden, bevor ein Ziel, das nur Text akzeptiert, seine Struktur empfangen kann.
Set
Ein Set ist eine Sammlung eindeutiger Werte beliebigen Typs, die beim Durchlaufen die Einfügereihenfolge erhält und keine Positionen mit Indizes hat.
Wird "ready" zweimal hinzugefügt, bleibt ein Wert erhalten; werden zwei separate übereinstimmende Datensätze hinzugefügt, bleiben beide erhalten.
Sichere Ganzzahl
Eine sichere Ganzzahl ist eine ganze Zahl von -9007199254740991 bis einschließlich 9007199254740991; in diesem Bereich hält JavaScript Number jede ganze Zahl unterscheidbar und exakt.
Ein Bezeichner, der den sicheren Bereich überschreitet, kann als JSON-Zeichenkette gesendet werden, um jede Ziffer zu erhalten.
Spread für iterierbare Objekte
Spread für iterierbare Objekte entfaltet ein iterierbares Objekt in einzelne Arrayelemente oder Aufrufargumente und liest dessen Werte der Reihe nach.
Math.max(...measurements) übergibt jedes Arrayelement als separates Argument an die Funktion.
Standardwert bei der Destrukturierung
Ein Standardwert bei der Destrukturierung ersetzt einen ausgewählten Wert undefined, auch bei einem fehlenden Feld oder einer fehlenden Position.
In const { count = 2 } = { count: null }; bleibt das ausdrücklich angegebene null trotz des Standardwerts erhalten.
structuredClone
structuredClone kopiert unterstützte verschachtelte JavaScript-Werte einschließlich zirkulärer Strukturen, lehnt aber Funktionswerte ab.
Ein Datensatz mit einfachen Arrays kann geklont werden; enthält er eine Methode, verursacht das einen DataCloneError.
Strukturprüfung
Eine Strukturprüfung überprüft vor der Verwendung eines geparsten Werts, ob er die Felder, Behälterarten und Werttypen besitzt, die das Programm benötigt.
Gültiges JSON mit einem count-Wert als Zeichenkette muss weiterhin geprüft werden, bevor ein Programm dieses Feld als Zahl behandelt.
Symmetrische Differenz
Eine symmetrische Differenz enthält Werte, die in genau einer von zwei Sammlungen vorhanden sind, und schließt jeden gemeinsamen Wert aus.
Der Vergleich zweier Tag-Sets auf diese Weise findet Tags, die zu einer Liste gehören, aber nicht zu beiden.
SyntaxError
Ein SyntaxError zeigt ungültige Syntax an, etwa fehlerhaften Text, der an JSON.parse übergeben wurde.
Ein abschließendes Komma in externem JSON kann mit try...catch abgefangen werden, sodass das Programm den Fehler behandeln kann.

T

Teilmenge
Eine Teilmenge ist eine Sammlung, deren jeder Wert auch zu einer anderen Sammlung gehört, selbst wenn die beiden Sammlungen gleich sind.
Ein Set erforderlicher Berechtigungen ist nur dann eine Teilmenge der gewährten Berechtigungen, wenn jeder erforderliche Wert gewährt wurde.
this
Das Schlüsselwort this bezeichnet den aktuellen Kontext einer Funktion; reguläre Funktionen erhalten ihn normalerweise durch den Aufruf und Pfeilfunktionen behalten einen äußeren Kontext.
Dieselbe ungebundene reguläre Lesemethode kann verschiedene Objekte lesen, wenn sie über verschiedene Empfängerobjekte aufgerufen wird.
Tiefe Kopie
Eine tiefe Kopie erstellt neben einem neuen äußeren Wert auch unabhängige verschachtelte Daten, soweit die Kopiermethode deren Typen unterstützt.
Nach einem unterstützten structuredClone bleibt das ursprüngliche Feld unverändert, wenn du ein kopiertes verschachteltes Feld bearbeitest.
toJSON
Eine toJSON-Methode gibt die gewählte JSON-geeignete Darstellung eines Objekts zurück, die stringify anstelle des ursprünglichen Objekts schreibt.
Ein Messobjekt kann einen kleineren einfachen Datensatz zurückgeben, der die für den Austausch vorgesehenen Felder enthält.

U

Umbenennungsmuster
Ein Umbenennungsmuster liest eine Eigenschaft mithilfe eines Doppelpunkts in eine Variable mit einem anderen lokalen Namen.
const { title: label } = page; erstellt label, ohne eine Variable namens title zu deklarieren.
Unveränderliche Aktualisierung
Eine unveränderliche Aktualisierung erstellt neue Behälter für die Daten, die sich ändern, und erhält die ursprünglichen Behälter sowie unveränderte gemeinsam genutzte Werte.
Ein map-Callback kann für den geänderten Datensatz eine Spread-Kopie zurückgeben und jeden nicht betroffenen Datensatz wiederverwenden.

Ü

Übersprungene Position
Eine übersprungene Position nimmt in einem Array-Destrukturierungsmuster einen Wert auf, ohne ihn zu benennen.
const [, second] = colors; überspringt die erste Farbe und benennt nur den nächsten gelieferten Wert.

V

Vereinigungsmenge
Eine Vereinigungsmenge enthält jeden Wert, der in mindestens einer von zwei Sammlungen vorhanden ist; gemeinsame Werte sind im resultierenden Set nur einmal enthalten.
Wenn eine Gruppe Ana und Bo und eine andere Bo und Cai enthält, umfasst ihre Vereinigungsmenge alle drei Personen.
Verschachtelte Daten
Verschachtelte Daten enthalten Objekte oder Arrays innerhalb anderer Objekte oder Arrays, sodass ein Pfad mehrere Schritte durchlaufen muss, um einen Wert zu erreichen.
report.readings[0].tempC liest eine Liste, ihren ersten Datensatz und dann ein Temperaturfeld.
Verschachteltes Muster
Ein verschachteltes Muster wählt beim Entpacken einer äußeren Struktur Werte aus einer inneren Struktur aus.
const { owner: { name } } = item; benötigt ein owner-Objekt und deklariert nur name.

W

WeakMap
Eine WeakMap ordnet Objekt- oder nicht registrierten Symbolschlüsseln Werte zu, ohne anderweitig unerreichbare Schlüssel am Leben zu halten.
Eine WeakMap kann einem Objekt Metadaten zuordnen, ohne diesem Objekt Felder hinzuzufügen oder eine Eintragsliste bereitzustellen.
WeakSet
Ein WeakSet erfasst die Zugehörigkeit von Objekten oder nicht registrierten Symbolen, ohne anderweitig unerreichbare Mitglieder am Leben zu halten, und lässt sich nicht durchlaufen.
Ein WeakSet kann verarbeitete Objekte markieren, ohne sie allein deshalb zu behalten, weil sie einmal verarbeitet wurden.

Z

Zirkuläre Referenz
Eine zirkuläre Referenz ist ein Pfad von Objektreferenzen, der zu einem bereits auf diesem Pfad liegenden Objekt zurückführt und den gewöhnliches JSON nicht kodieren kann.
Das Hinzufügen von record.self = record führt dazu, dass das gewöhnliche JSON.stringify für diesen Datensatz einen TypeError auslöst.
Zugehörigkeitsprüfung
Eine Zugehörigkeitsprüfung fragt, ob ein Schlüssel oder Wert in einer Sammlung vorhanden ist, unabhängig von den unter diesem Schlüssel gespeicherten Daten.
map.has(key) kann einen vorhandenen Eintrag finden, selbst wenn map.get(key) undefined zurückgibt.

Über diese Einheit

Von StudeliFehler melden

Erstelle deine eigenen Lernmaterialien

Mach aus deinen Notizen, Folien und Dokumenten Lernleitfäden, Übungsfragen, Karteikarten und 6 weitere Tools.

Jetzt starten