Die beiden am häufigsten verwendeten Datenstrukturen in JavaScript sind Object
und Array
.
Mit Objekten können wir eine einzelne Entität erstellen, die Datenelemente nach Schlüssel speichert.
Mithilfe von Arrays können wir Datenelemente in einer geordneten Liste zusammenfassen.
Wenn wir diese jedoch an eine Funktion übergeben, benötigen wir möglicherweise nicht alles. Die Funktion erfordert möglicherweise nur bestimmte Elemente oder Eigenschaften.
Destrukturierende Zuweisungen sind eine spezielle Syntax, die es uns ermöglicht, Arrays oder Objekte in eine Reihe von Variablen zu „entpacken“, da dies manchmal praktischer ist.
Die Destrukturierung funktioniert auch gut mit komplexen Funktionen, die viele Parameter, Standardwerte usw. haben. Bald werden wir das sehen.
Hier ist ein Beispiel dafür, wie ein Array in Variablen zerlegt wird:
// wir haben ein Array mit einem Vor- und Nachnamen let arr = ["John", "Smith"] // Destrukturierungsauftrag // setzt firstName = arr[0] // und Nachname = arr[1] let [Vorname, Nachname] = arr; alarm(vorname); // John Warnung(Nachname); // Smith
Jetzt können wir mit Variablen statt mit Array-Mitgliedern arbeiten.
In Kombination mit split
oder anderen Array-Rückgabemethoden sieht es großartig aus:
let [Vorname, Nachname] = "John Smith".split(' '); alarm(vorname); // John Warnung(Nachname); // Smith
Wie Sie sehen, ist die Syntax einfach. Es gibt jedoch einige seltsame Details. Sehen wir uns weitere Beispiele an, um es besser zu verstehen.
„Destrukturierend“ bedeutet nicht „destruktiv“.
Es wird „destrukturierende Zuweisung“ genannt, weil es durch das Kopieren von Elementen in Variablen „destrukturiert“. Das Array selbst wird jedoch nicht verändert.
Es ist nur eine kürzere Art zu schreiben:
// let [Vorname, Nachname] = arr; let firstName = arr[0]; let Nachname = arr[1];
Ignorieren Sie Elemente mit Kommas
Über ein zusätzliches Komma können auch unerwünschte Elemente des Arrays weggeworfen werden:
// zweites Element wird nicht benötigt let [Vorname, Titel] = ["Julius", "Caesar", "Konsul", "der Römischen Republik"]; Alert( Titel ); // Konsul
Im obigen Code wird das zweite Element des Arrays übersprungen, das dritte wird title
zugewiesen und die restlichen Array-Elemente werden ebenfalls übersprungen (da es keine Variablen für sie gibt).
Funktioniert mit jedem Iterable auf der rechten Seite
…Eigentlich können wir es mit jedem iterierbaren Array verwenden, nicht nur mit Arrays:
sei [a, b, c] = „abc“; // ["a", "b", "c"] let [one, two, three] = new Set([1, 2, 3]);
Das funktioniert, weil eine destrukturierende Zuweisung intern durch Iteration über den richtigen Wert funktioniert. Es ist eine Art Syntax-Zucker für den Aufruf for..of
über dem Wert rechts von =
und das Zuweisen der Werte.
Weisen Sie alles auf der linken Seite zu
Auf der linken Seite können wir beliebige „Assignables“ verwenden.
Zum Beispiel eine Objekteigenschaft:
let user = {}; [Benutzername, Benutzername] = „John Smith“.split(' '); Alert(Benutzername); // John Alert(Benutzer.Nachname); // Smith
Schleife mit .entries()
Im vorherigen Kapitel haben wir die Methode Object.entries(obj) gesehen.
Wir können es mit Destrukturierung verwenden, um die Schlüssel und Werte eines Objekts zu durchlaufen:
let user = { Name: „John“, Alter: 30 }; // Schleife über die Schlüssel und Werte for (let [key, value] of Object.entries(user)) { alarm(`${key}:${value}`); // Name:John, dann Alter:30 }
Der ähnliche Code für eine Map
ist einfacher, da er iterierbar ist:
let user = new Map(); user.set("name", "John"); user.set("Alter", "30"); // Map iteriert als [Schlüssel, Wert]-Paare, was für die Destrukturierung sehr praktisch ist for (let [Schlüssel, Wert] des Benutzers) { alarm(`${key}:${value}`); // Name:John, dann Alter:30 }
Trick zum Austauschen von Variablen
Es gibt einen bekannten Trick zum Vertauschen der Werte zweier Variablen mithilfe einer destrukturierenden Zuweisung:
let Guest = „Jane“; let admin = "Pete"; // Lassen Sie uns die Werte vertauschen: make guest=Pete, admin=Jane [Gast, Administrator] = [Administrator, Gast]; alarm(`${guest} ${admin}`); // Pete Jane (erfolgreich getauscht!)
Hier erstellen wir ein temporäres Array aus zwei Variablen und zerstören es sofort in vertauschter Reihenfolge.
Auf diese Weise können wir mehr als zwei Variablen austauschen.
Wenn das Array länger als die Liste links ist, werden die „zusätzlichen“ Elemente normalerweise weggelassen.
Hier werden beispielsweise nur zwei Elemente verwendet und der Rest wird einfach ignoriert:
let [name1, name2] = ["Julius", "Caesar", "Konsul", "der Römischen Republik"]; Warnung(Name1); // Julius alarm(name2); // Cäsar // Weitere Elemente werden nirgendwo zugeordnet
Wenn wir auch alles Folgende zusammenfassen möchten, können wir einen weiteren Parameter hinzufügen, der „den Rest“ mit drei Punkten "..."
erhält:
let [name1, name2, ...rest] = ["Julius", "Caesar", "Konsul", "der Römischen Republik"]; // rest ist ein Array von Elementen, beginnend mit dem dritten alarm(rest[0]); // Konsul alarm(rest[1]); // der Römischen Republik alarm(rest.length); // 2
Der Wert von rest
ist das Array der verbleibenden Array-Elemente.
Wir können anstelle von rest
einen beliebigen anderen Variablennamen verwenden. Stellen Sie jedoch sicher, dass vor ihm drei Punkte stehen und er in der Destrukturierungszuweisung an letzter Stelle steht.
let [name1, name2, ...titles] = ["Julius", "Caesar", "Consul", "of the Roman Republic"]; // now titles = ["Konsul", "der Römischen Republik"]
Wenn das Array kürzer ist als die Liste der Variablen auf der linken Seite, treten keine Fehler auf. Fehlende Werte gelten als undefiniert:
let [Vorname, Nachname] = []; alarm(vorname); // undefiniert Warnung(Nachname); // undefiniert
Wenn wir möchten, dass der fehlende Wert durch einen „Standard“-Wert ersetzt wird, können wir ihn mit =
bereitstellen:
// Standardwerte let [name = "Gast", Nachname = "Anonymous"] = ["Julius"]; Warnung(Name); // Julius (aus Array) Warnung(Nachname); // Anonym (Standard verwendet)
Standardwerte können komplexere Ausdrücke oder sogar Funktionsaufrufe sein. Sie werden nur ausgewertet, wenn der Wert nicht angegeben wird.
Hier verwenden wir beispielsweise die prompt
für zwei Standardeinstellungen:
// führt nur die Eingabeaufforderung für den Nachnamen aus let [Name = prompt('Name?'), Nachname = Prompt('Nachname?')] = ["Julius"]; alarm(name); // Julius (aus Array) Warnung(Nachname); // was auch immer die Eingabeaufforderung erhält
Bitte beachten Sie: Die prompt
wird nur für den fehlenden Wert ( surname
) ausgeführt.
Der Destrukturierungsauftrag funktioniert auch mit Objekten.
Die grundlegende Syntax lautet:
sei {var1, var2} = {var1:…, var2:…}
Auf der rechten Seite sollte ein Objekt vorhanden sein, das wir in Variablen aufteilen möchten. Die linke Seite enthält ein objektartiges „Muster“ für entsprechende Eigenschaften. Im einfachsten Fall ist das eine Liste von Variablennamen in {...}
.
Zum Beispiel:
let Optionen = { Titel: „Menü“, Breite: 100, Höhe: 200 }; let {title, width, height} = Optionen; Warnung(Titel); // Speisekarte Warnung (Breite); // 100 Warnung(Höhe); // 200
Den entsprechenden Variablen werden die Eigenschaften options.title
, options.width
und options.height
zugewiesen.
Die Reihenfolge spielt keine Rolle. Das funktioniert auch:
// die Reihenfolge in let {...} geändert let {height, width, title} = { title: "Menu", height: 200, width: 100 }
Das Muster auf der linken Seite ist möglicherweise komplexer und legt die Zuordnung zwischen Eigenschaften und Variablen fest.
Wenn wir einer Variablen mit einem anderen Namen eine Eigenschaft zuweisen möchten, beispielsweise options.width
in die Variable „ w
einfügen, können wir den Variablennamen mithilfe eines Doppelpunkts festlegen:
let Optionen = { Titel: „Menü“, Breite: 100, Höhe: 200 }; // { sourceProperty: targetVariable } let {width: w, height: h, title} = Optionen; // Breite -> w // Höhe -> h // Titel -> Titel Warnung(Titel); // Speisekarte alarm(w); // 100 alarm(h); // 200
Der Doppelpunkt zeigt „was: wohin geht“. Im obigen Beispiel geht die width
auf w
, die height
auf h
und title
wird demselben Namen zugewiesen.
Für potenziell fehlende Eigenschaften können wir mit "="
Standardwerte festlegen, etwa so:
let Optionen = { Titel: „Menü“ }; let {width = 100, height = 200, title} = Optionen; Warnung(Titel); // Speisekarte Warnung (Breite); // 100 Warnung(Höhe); // 200
Genau wie bei Arrays oder Funktionsparametern können Standardwerte beliebige Ausdrücke oder sogar Funktionsaufrufe sein. Sie werden ausgewertet, wenn der Wert nicht angegeben wird.
Im folgenden Code fragt prompt
nach width
, aber nicht nach title
:
let Optionen = { Titel: „Menü“ }; let {width = prompt("width?"), title = prompt("title?")} = options; Warnung(Titel); // Speisekarte Warnung (Breite); // (was auch immer das Ergebnis der Eingabeaufforderung ist)
Wir können auch Doppelpunkt und Gleichheit kombinieren:
let Optionen = { Titel: „Menü“ }; let {width: w = 100, height: h = 200, title} = options; Warnung(Titel); // Speisekarte alarm(w); // 100 alarm(h); // 200
Wenn wir ein komplexes Objekt mit vielen Eigenschaften haben, können wir nur das extrahieren, was wir brauchen:
let Optionen = { Titel: „Menü“, Breite: 100, Höhe: 200 }; // Titel nur als Variable extrahieren let { title } = Optionen; Warnung(Titel); // Speisekarte
Was ist, wenn das Objekt mehr Eigenschaften hat, als wir Variablen haben? Können wir einige nehmen und den „Rest“ dann irgendwo verteilen?
Wir können das Restmuster verwenden, genau wie wir es bei Arrays getan haben. Es wird von einigen älteren Browsern (IE, verwenden Sie Babel zum Polyfillen) nicht unterstützt, funktioniert aber in modernen.
Es sieht so aus:
let Optionen = { Titel: „Menü“, Höhe: 200, Breite: 100 }; // title = Eigenschaft mit dem Namen title // rest = Objekt mit den restlichen Eigenschaften let {title, ...rest} = Optionen; // jetzt title="Menü", rest={height: 200, width: 100} alarm(rest.height); // 200 alarm(rest.width); // 100
Gotcha, wenn es keine let
gibt
In den obigen Beispielen wurden Variablen direkt in der Zuweisung deklariert: let {…} = {…}
. Natürlich könnten wir auch vorhandene Variablen verwenden, ohne let
. Aber es gibt einen Haken.
Das wird nicht funktionieren:
let Titel, Breite, Höhe; // Fehler in dieser Zeile {title, width, height} = {title: "Menü", width: 200, height: 100};
Das Problem besteht darin, dass JavaScript {...}
im Hauptcodefluss (nicht innerhalb eines anderen Ausdrucks) als Codeblock behandelt. Solche Codeblöcke können zum Gruppieren von Anweisungen wie folgt verwendet werden:
{ // ein Codeblock let message = "Hallo"; // ... Warnung( Nachricht); }
Hier geht JavaScript also davon aus, dass wir einen Codeblock haben, weshalb ein Fehler vorliegt. Wir wollen stattdessen Destrukturierung.
Um JavaScript zu zeigen, dass es sich nicht um einen Codeblock handelt, können wir den Ausdruck in Klammern (...)
setzen:
let Titel, Breite, Höhe; // Okay, jetzt ({title, width, height} = {title: „Menü“, width: 200, height: 100}); Alert( Titel ); // Speisekarte
Wenn ein Objekt oder ein Array andere verschachtelte Objekte und Arrays enthält, können wir komplexere Muster auf der linken Seite verwenden, um tiefere Teile zu extrahieren.
Im folgenden Code verfügt options
über ein weiteres Objekt in der Eigenschaft „ size
“ und ein Array in der Eigenschaft „ items
. Das Muster auf der linken Seite der Zuweisung hat die gleiche Struktur, um daraus Werte zu extrahieren:
let Optionen = { Größe: { Breite: 100, Höhe: 200 }, Elemente: [„Kuchen“, „Donut“], extra: wahr }; // Destrukturierungszuweisung aus Gründen der Übersichtlichkeit in mehrere Zeilen aufgeteilt lassen { size: { // Größe hier eingeben Breite, Höhe }, items: [item1, item2], // Elemente hier zuweisen title = „Menü“ // nicht im Objekt vorhanden (Standardwert wird verwendet) } = Optionen; Warnung(Titel); // Speisekarte Warnung (Breite); // 100 Warnung(Höhe); // 200 alarm(item1); // Kuchen alarm(item2); // Donut
Alle Eigenschaften des options
außer extra
, das im linken Teil fehlt, werden den entsprechenden Variablen zugewiesen:
Schließlich haben wir width
, height
, item1
, item2
und title
vom Standardwert.
Beachten Sie, dass es keine Variablen für size
und items
gibt, da wir stattdessen deren Inhalt verwenden.
Es gibt Zeiten, in denen eine Funktion viele Parameter hat, von denen die meisten optional sind. Das gilt insbesondere für Benutzeroberflächen. Stellen Sie sich eine Funktion vor, die ein Menü erstellt. Es kann eine Breite, eine Höhe, einen Titel, eine Artikelliste usw. haben.
Hier ist eine schlechte Art, eine solche Funktion zu schreiben:
Funktion showMenu(title = "Untitled", width = 200, height = 100, items = []) { // ... }
Im wirklichen Leben besteht das Problem darin, sich die Reihenfolge der Argumente zu merken. Normalerweise versuchen IDEs uns zu helfen, insbesondere wenn der Code gut dokumentiert ist, aber trotzdem ... Ein weiteres Problem besteht darin, wie man eine Funktion aufruft, wenn die meisten Parameter standardmäßig in Ordnung sind.
So was?
// undefiniert, wobei Standardwerte in Ordnung sind showMenu("Mein Menü", undefiniert, undefiniert, ["Item1", "Item2"])
Das ist hässlich. Und wird unleserlich, wenn wir uns mit mehr Parametern befassen.
Destrukturierung kommt zur Rettung!
Wir können Parameter als Objekt übergeben und die Funktion destrukturiert sie sofort in Variablen:
// Wir übergeben das Objekt an die Funktion let Optionen = { Titel: „Mein Menü“, Elemente: ["Item1", "Item2"] }; // ...und es wird sofort auf Variablen erweitert function showMenu({title = "Untitled", width = 200, height = 100, items = []}) { // Titel, Artikel – entnommen aus Optionen, // Breite, Höhe – verwendete Standardwerte alarm( `${title} ${width} ${height}` ); // Mein Menü 200 100 Alert( Elemente ); // Artikel1, Artikel2 } showMenu(Optionen);
Wir können auch eine komplexere Destrukturierung mit verschachtelten Objekten und Doppelpunktzuordnungen verwenden:
let Optionen = { Titel: „Mein Menü“, Elemente: ["Item1", "Item2"] }; Funktion showMenu({ title = „Ohne Titel“, Breite: w = 100, // Breite geht an w Höhe: h = 200, // Höhe geht zu h items: [item1, item2] // items erstes Element geht zu item1, zweites zu item2 }) { alarm( `${title} ${w} ${h}` ); // Mein Menü 100 200 alarm( item1 ); // Artikel1 alarm( item2 ); // Item2 } showMenu(Optionen);
Die vollständige Syntax ist dieselbe wie für eine Destrukturierungsaufgabe:
Funktion({ incomingProperty: varName = defaultValue ... })
Dann gibt es für ein Parameterobjekt eine Variable varName
für die Eigenschaft incomingProperty
, standardmäßig mit defaultValue
.
Bitte beachten Sie, dass eine solche Destrukturierung davon ausgeht, dass showMenu()
tatsächlich ein Argument hat. Wenn wir standardmäßig alle Werte wünschen, sollten wir ein leeres Objekt angeben:
showMenu({}); // ok, alle Werte sind Standardwerte showMenu(); // Dies würde einen Fehler ergeben
Wir können dies beheben, indem wir {}
zum Standardwert für das gesamte Parameterobjekt machen:
Funktion showMenu({ title = "Menü", Breite = 100, Höhe = 200 } = {}) { alarm( `${title} ${width} ${height}` ); } showMenu(); // Menü 100 200
Im obigen Code ist das gesamte Argumentobjekt standardmäßig {}
, es gibt also immer etwas zu destrukturieren.
Die Destrukturierungszuweisung ermöglicht die sofortige Zuordnung eines Objekts oder Arrays zu vielen Variablen.
Die vollständige Objektsyntax:
let {prop : varName = defaultValue, ...rest} = object
Dies bedeutet, dass die Eigenschaft prop
in die Variable varName
eingefügt werden sollte und, wenn keine solche Eigenschaft vorhanden ist, der default
verwendet werden sollte.
Objekteigenschaften, die keine Zuordnung haben, werden auf das rest
Objekt kopiert.
Die vollständige Array-Syntax:
let [item1 = defaultValue, item2, ...rest] = array
Das erste Element geht an item1
; der zweite geht in item2
, und der Rest sorgt dafür, dass das Array rest
.
Es ist möglich, Daten aus verschachtelten Arrays/Objekten zu extrahieren, dafür muss die linke Seite die gleiche Struktur haben wie die rechte.
Wichtigkeit: 5
Wir haben ein Objekt:
let user = { Name: „John“, Jahre: 30 };
Schreiben Sie die Destrukturierungsaufgabe, die lautet:
name
in die Variable name
einfügen.
years
Eigenschaft in die Variable age
ein.
isAdmin
Eigenschaft in die Variable isAdmin
(false, wenn keine solche Eigenschaft vorhanden ist)
Hier ist ein Beispiel für die Werte nach Ihrer Zuweisung:
let user = { name: "John", Jahre: 30 }; // Ihr Code auf der linken Seite: // ... = Benutzer alarm( name ); // John Alarm(Alter); // 30 alarm( isAdmin ); // FALSCH
let user = { Name: „John“, Jahre: 30 }; let {name, years: age, isAdmin = false} = user; alarm( name ); // John Alarm(Alter); // 30 alarm( isAdmin ); // FALSCH
Wichtigkeit: 5
Es gibt ein salaries
:
lass Gehälter = { „John“: 100, „Pete“: 300, „Maria“: 250 };
Erstellen Sie die Funktion topSalary(salaries)
, die den Namen der bestbezahlten Person zurückgibt.
Wenn salaries
leer ist, sollte null
zurückgegeben werden.
Wenn es mehrere bestbezahlte Personen gibt, geben Sie eine davon zurück.
PS: Verwenden Sie Object.entries
und Destrukturierung, um über Schlüssel/Wert-Paare zu iterieren.
Öffnen Sie eine Sandbox mit Tests.
Funktion topSalary(salaries) { sei maxSalary = 0; let maxName = null; for(const [Name, Gehalt] von Object.entries(Gehälter)) { if (maxSalary < Gehalt) { maxSalary = Gehalt; maxName = Name; } } return maxName; }
Öffnen Sie die Lösung mit Tests in einer Sandbox.