Wie wir aus dem Kapitel Datentypen wissen, gibt es in JavaScript acht Datentypen. Sieben davon werden „primitiv“ genannt, weil ihre Werte nur ein einziges Ding enthalten (sei es eine Zeichenfolge oder eine Zahl oder was auch immer).
Im Gegensatz dazu werden Objekte zum Speichern verschlüsselter Sammlungen verschiedener Daten und komplexerer Entitäten verwendet. In JavaScript durchdringen Objekte nahezu jeden Aspekt der Sprache. Wir müssen sie also zuerst verstehen, bevor wir uns irgendwo anders ausführlich damit befassen.
Ein Objekt kann mit Zahlenklammern {…}
mit einer optionalen Liste von Eigenschaften erstellt werden. Eine Eigenschaft ist ein „Schlüssel:Wert“-Paar, wobei key
eine Zeichenfolge ist (auch „Eigenschaftsname“ genannt) und value
ein beliebiger Wert sein kann.
Wir können uns ein Objekt als einen Schrank mit signierten Akten vorstellen. Jedes Datenelement wird durch den Schlüssel in seiner Datei gespeichert. Es ist einfach, eine Datei anhand ihres Namens zu finden oder eine Datei hinzuzufügen/entfernen.
Ein leeres Objekt („leerer Schrank“) kann mit einer von zwei Syntaxen erstellt werden:
let user = new Object(); // Syntax „Objektkonstruktor“. let user = {}; // Syntax „Objektliteral“.
Normalerweise werden die Zahlenklammern {...}
verwendet. Diese Deklaration wird als Objektliteral bezeichnet.
Wir können einige Eigenschaften sofort als „Schlüssel:Wert“-Paare in {...}
einfügen:
let user = { // ein Objekt name: „John“, // über den Schlüssel „name“ den Wert „John“ speichern Alter: 30 // Mit dem Schlüssel „Alter“ den Wert 30 speichern };
Eine Eigenschaft hat einen Schlüssel (auch bekannt als „Name“ oder „Bezeichner“) vor dem Doppelpunkt ":"
und einen Wert rechts davon.
Im user
gibt es zwei Eigenschaften:
Die erste Eigenschaft hat den Namen "name"
und den Wert "John"
.
Der zweite hat den Namen "age"
und den Wert 30
.
Das resultierende user
kann man sich als Schrank mit zwei signierten Dateien mit der Bezeichnung „Name“ und „Alter“ vorstellen.
Wir können jederzeit Dateien hinzufügen, entfernen und lesen.
Auf Eigenschaftswerte kann über die Punktnotation zugegriffen werden:
// Eigenschaftswerte des Objekts abrufen: alarm( user.name ); // John alarm( user.age ); // 30
Der Wert kann von beliebigem Typ sein. Fügen wir einen booleschen Wert hinzu:
user.isAdmin = true;
Um eine Eigenschaft zu entfernen, können wir den delete
verwenden:
user.age löschen;
Wir können auch Eigenschaftsnamen mit mehreren Wörtern verwenden, diese müssen dann jedoch in Anführungszeichen gesetzt werden:
let user = { Name: „John“, Alter: 30, „mag Vögel“: true // Mehrwort-Eigenschaftsname muss in Anführungszeichen gesetzt werden };
Die letzte Eigenschaft in der Liste kann mit einem Komma enden:
let user = { Name: „John“, Alter: 30, }
Dies wird als „nachgestelltes“ oder „hängendes“ Komma bezeichnet. Erleichtert das Hinzufügen/Entfernen/Verschieben von Eigenschaften, da alle Linien gleich werden.
Bei Mehrworteigenschaften funktioniert der Punktzugriff nicht:
// Dies würde einen Syntaxfehler ergeben user.likes Vögel = wahr
JavaScript versteht das nicht. Es geht davon aus, dass wir user.likes
ansprechen, und gibt dann einen Syntaxfehler aus, wenn es auf unerwartete birds
stößt.
Der Punkt erfordert, dass der Schlüssel ein gültiger Variablenbezeichner ist. Das bedeutet: enthält keine Leerzeichen, beginnt nicht mit einer Ziffer und enthält keine Sonderzeichen ( $
und _
sind erlaubt).
Es gibt eine alternative „eckige Klammernotation“, die mit jeder Zeichenfolge funktioniert:
let user = {}; // Satz user["mag Vögel"] = true; // erhalten Alert(user["mag Vögel"]); // WAHR // löschen Benutzer löschen["mag Vögel"];
Jetzt ist alles in Ordnung. Bitte beachten Sie, dass die Zeichenfolge in den Klammern ordnungsgemäß in Anführungszeichen gesetzt wird (jede Art von Anführungszeichen reicht aus).
Eckige Klammern bieten auch eine Möglichkeit, den Eigenschaftsnamen als Ergebnis eines beliebigen Ausdrucks – im Gegensatz zu einer Literalzeichenfolge – zu erhalten, beispielsweise aus einer Variablen wie folgt:
let key = „mag Vögel“; // dasselbe wie user["mag Vögel"] = true; user[key] = true;
Dabei kann der variable key
zur Laufzeit berechnet werden oder von der Benutzereingabe abhängen. Und dann nutzen wir es, um auf das Grundstück zuzugreifen. Das gibt uns ein großes Maß an Flexibilität.
Zum Beispiel:
let user = { Name: „John“, Alter: 30 }; let key = prompt("Was möchten Sie über den Benutzer wissen?", "Name"); // Zugriff über Variable alarm( user[key] ); // John (wenn „Name“ eingeben)
Die Punktnotation kann nicht auf ähnliche Weise verwendet werden:
let user = { Name: „John“, Alter: 30 }; let key = "name"; alarm( user.key ) // undefiniert
Beim Erstellen eines Objekts können wir eckige Klammern in einem Objektliteral verwenden. Das nennt man berechnete Eigenschaften .
Zum Beispiel:
let Fruit = prompt("Welche Frucht soll ich kaufen?", "Apple"); let bag = { [Frucht]: 5, // Der Name der Eigenschaft wird von der Variablen Frucht übernommen }; alarm( bag.apple ); // 5 wenn Fruit="Apple"
Die Bedeutung einer berechneten Eigenschaft ist einfach: [fruit]
bedeutet, dass der Eigenschaftsname von fruit
abgeleitet sein sollte.
Wenn ein Besucher also "apple"
eingibt, wird aus bag
{apple: 5}
.
Im Wesentlichen funktioniert das genauso wie:
let Fruit = prompt("Welche Frucht soll ich kaufen?", "Apple"); let bag = {}; // Eigenschaftsnamen aus der Fruchtvariablen übernehmen Beutel[Frucht] = 5;
…Aber sieht schöner aus.
Wir können komplexere Ausdrücke in eckigen Klammern verwenden:
let Fruit = 'Apfel'; let bag = { [Frucht + 'Computer']: 5 // bag.appleComputers = 5 };
Eckige Klammern sind viel leistungsfähiger als die Punktnotation. Sie erlauben beliebige Eigenschaftsnamen und Variablen. Allerdings sind sie auch umständlicher zu schreiben.
Wenn Eigenschaftsnamen bekannt und einfach sind, wird daher meistens der Punkt verwendet. Und wenn wir etwas Komplexeres brauchen, dann wechseln wir zu eckigen Klammern.
In echtem Code verwenden wir häufig vorhandene Variablen als Werte für Eigenschaftsnamen.
Zum Beispiel:
Funktion makeUser(name, age) { zurückkehren { Name: Name, Alter: Alter, // ...andere Eigenschaften }; } let user = makeUser("John", 30); Alert(Benutzername); // John
Im obigen Beispiel haben Eigenschaften die gleichen Namen wie Variablen. Der Anwendungsfall, eine Eigenschaft aus einer Variablen zu erstellen, ist so häufig, dass es eine spezielle Abkürzung für den Eigenschaftswert gibt, um ihn zu verkürzen.
Anstelle von name:name
können wir einfach name
schreiben, etwa so:
Funktion makeUser(name, age) { zurückkehren { name, // dasselbe wie name: name Alter, // dasselbe wie Alter: Alter // ... }; }
Wir können sowohl normale Eigenschaften als auch Abkürzungen im selben Objekt verwenden:
let user = { name, // dasselbe wie name:name Alter: 30 };
Wie wir bereits wissen, kann eine Variable keinen Namen haben, der einem der sprachreservierten Wörter wie „for“, „let“, „return“ usw. entspricht.
Für eine Objekteigenschaft gibt es jedoch keine solche Einschränkung:
// Diese Eigenschaften sind in Ordnung sei obj = { für: 1, sei: 2, Rückkehr: 3 }; alarm( obj.for + obj.let + obj.return ); // 6
Kurz gesagt, es gibt keine Beschränkungen für Eigenschaftsnamen. Dabei kann es sich um beliebige Zeichenfolgen oder Symbole handeln (ein spezieller Typ für Bezeichner, der später behandelt wird).
Andere Typen werden automatisch in Strings konvertiert.
Beispielsweise wird eine Zahl 0
zu einer Zeichenfolge "0"
, wenn sie als Eigenschaftsschlüssel verwendet wird:
sei obj = { 0: „test“ // dasselbe wie „0“: „test“ }; // beide Alarme greifen auf die gleiche Eigenschaft zu (die Zahl 0 wird in String „0“ umgewandelt) alarm( obj["0"] ); // prüfen alarm( obj[0] ); // test (gleiche Eigenschaft)
Es gibt ein kleines Problem mit einer speziellen Eigenschaft namens __proto__
. Wir können es nicht auf einen Nicht-Objekt-Wert setzen:
sei obj = {}; obj.__proto__ = 5; // eine Nummer zuweisen alarm(obj.__proto__); // [Objekt Objekt] – der Wert ist ein Objekt, hat nicht wie beabsichtigt funktioniert
Wie wir dem Code entnehmen können, wird die Zuweisung zu einem Grundelement 5
ignoriert.
Wir werden die Besonderheiten von __proto__
in den folgenden Kapiteln behandeln und Möglichkeiten zur Behebung dieses Verhaltens vorschlagen.
Ein bemerkenswertes Merkmal von Objekten in JavaScript im Vergleich zu vielen anderen Sprachen ist, dass auf jede Eigenschaft zugegriffen werden kann. Es wird kein Fehler angezeigt, wenn die Eigenschaft nicht vorhanden ist!
Das Lesen einer nicht vorhandenen Eigenschaft gibt einfach undefined
zurück. So können wir ganz einfach testen, ob die Eigenschaft existiert:
let user = {}; alarm( user.noSuchProperty === undefiniert ); // true bedeutet „keine solche Eigenschaft“
Dafür gibt es auch einen speziellen Operator "in"
.
Die Syntax lautet:
„Schlüssel“ im Objekt
Zum Beispiel:
let user = { name: „John“, Alter: 30 }; Alert( „Alter“ im Benutzer); // true, user.age existiert alarm( „blabla“ in user ); // false, user.blabla existiert nicht
Bitte beachten Sie, dass auf der linken Seite ein Eigenschaftsname in
muss. Das ist normalerweise eine Zeichenfolge in Anführungszeichen.
Wenn wir Anführungszeichen weglassen, bedeutet das, dass eine Variable den tatsächlichen Namen enthalten sollte, der getestet werden soll. Zum Beispiel:
let user = { age: 30 }; let key = "Alter"; Alert(Benutzer eingeben); // wahr, Eigenschaft „Alter“ existiert
Warum gibt es den in
Operator? Reicht es nicht, mit undefined
zu vergleichen?
Nun, meistens funktioniert der Vergleich mit undefined
gut. Aber es gibt einen Sonderfall, wenn es fehlschlägt, "in"
aber korrekt funktioniert.
Dies ist der Fall, wenn eine Objekteigenschaft vorhanden ist, aber undefined
gespeichert wird:
sei obj = { Test: undefiniert }; alarm( obj.test ); // es ist undefiniert, also - keine solche Eigenschaft? alarm( „test“ in obj ); // wahr, die Eigenschaft existiert!
Im obigen Code ist die Eigenschaft obj.test
technisch gesehen vorhanden. Der in
-Operator funktioniert also richtig.
Situationen wie diese kommen sehr selten vor, da undefined
nicht explizit zugewiesen werden sollte. Meistens verwenden wir null
für „unbekannte“ oder „leere“ Werte. Der in
-Operator ist also ein exotischer Gast im Code.
Um alle Schlüssel eines Objekts zu durchlaufen, gibt es eine spezielle Form der Schleife: for..in
. Dies ist etwas völlig anderes als das for(;;)
-Konstrukt, das wir zuvor untersucht haben.
Die Syntax:
for (Objekt eingeben) { // führt den Hauptteil für jeden Schlüssel unter den Objekteigenschaften aus }
Lassen Sie uns zum Beispiel alle Eigenschaften von user
ausgeben:
let user = { Name: „John“, Alter: 30, isAdmin: wahr }; for (Benutzer eingeben lassen) { // Schlüssel alarm( key ); // Name, Alter, isAdmin // Werte für die Schlüssel alarm( user[key] ); // John, 30, stimmt }
Beachten Sie, dass alle „for“-Konstrukte es uns ermöglichen, die Schleifenvariable innerhalb der Schleife zu deklarieren, wie hier let key
.
Außerdem könnten wir hier anstelle von key
einen anderen Variablennamen verwenden. Beispielsweise wird auch "for (let prop in obj)"
häufig verwendet.
Sind Objekte geordnet? Mit anderen Worten: Wenn wir ein Objekt durchlaufen, erhalten wir dann alle Eigenschaften in derselben Reihenfolge, in der sie hinzugefügt wurden? Können wir uns darauf verlassen?
Die kurze Antwort lautet: „in besonderer Weise geordnet“: Ganzzahlige Eigenschaften werden sortiert, andere erscheinen in der Erstellungsreihenfolge. Die Details folgen.
Betrachten wir als Beispiel ein Objekt mit den Telefoncodes:
let codes = { „49“: „Deutschland“, „41“: „Schweiz“, „44“: „Großbritannien“, // .., „1“: „USA“ }; for (Code in Codes lassen) { Warnung(Code); // 1, 41, 44, 49 }
Das Objekt kann verwendet werden, um dem Benutzer eine Liste von Optionen vorzuschlagen. Wenn wir eine Website hauptsächlich für ein deutsches Publikum erstellen, möchten wir wahrscheinlich, dass 49
die erste ist.
Aber wenn wir den Code ausführen, sehen wir ein völlig anderes Bild:
USA (1) geht zuerst
dann die Schweiz (41) und so weiter.
Die Telefoncodes werden in aufsteigender Reihenfolge angezeigt, da es sich um Ganzzahlen handelt. Wir sehen also 1, 41, 44, 49
.
Ganzzahlige Eigenschaften? Was ist das?
Der Begriff „Ganzzahleigenschaft“ bezeichnet hier eine Zeichenfolge, die ohne Änderung in eine Ganzzahl umgewandelt werden kann.
"49"
ist also ein ganzzahliger Eigenschaftsname, denn wenn er in eine ganze Zahl und zurück umgewandelt wird, ist er immer noch derselbe. Aber "+49"
und "1.2"
sind nicht:
// Number(...) wird explizit in eine Zahl konvertiert // Math.trunc ist eine integrierte Funktion, die den Dezimalteil entfernt alarm( String(Math.trunc(Number("49"))) ); // „49“, gleiche, ganzzahlige Eigenschaft alarm( String(Math.trunc(Number("+49"))) ); // „49“, nicht dasselbe „+49“ ⇒ keine Ganzzahleigenschaft alarm( String(Math.trunc(Number("1.2"))) ); // „1“, nicht gleich „1.2“ ⇒ keine Ganzzahleigenschaft
…Wenn die Schlüssel hingegen nicht ganzzahlig sind, werden sie in der Erstellungsreihenfolge aufgeführt, zum Beispiel:
let user = { Name: „John“, Nachname: „Smith“ }; user.age = 25; // noch eins hinzufügen // Nicht-ganzzahlige Eigenschaften werden in der Erstellungsreihenfolge aufgeführt for (let prop in user) { alarm( prop ); // Name, Nachname, Alter }
Um das Problem mit den Telefoncodes zu beheben, können wir also „schummeln“, indem wir die Codes nicht ganzzahlig machen. Es reicht aus, vor jedem Code ein Pluszeichen "+"
einzufügen.
So was:
let codes = { „+49“: „Deutschland“, „+41“: „Schweiz“, „+44“: „Großbritannien“, // .., „+1“: „USA“ }; for (Code in Codes lassen) { alarm( +code ); // 49, 41, 44, 1 }
Jetzt funktioniert es wie vorgesehen.
Objekte sind assoziative Arrays mit mehreren Besonderheiten.
Sie speichern Eigenschaften (Schlüssel-Wert-Paare), wobei:
Eigenschaftsschlüssel müssen Zeichenfolgen oder Symbole sein (normalerweise Zeichenfolgen).
Werte können von beliebigem Typ sein.
Um auf eine Eigenschaft zuzugreifen, können wir Folgendes verwenden:
Die Punktnotation: obj.property
.
Notation in eckigen Klammern obj["property"]
. Eckige Klammern ermöglichen die Übernahme des Schlüssels aus einer Variablen, z. B. obj[varWithKey]
.
Zusätzliche Betreiber:
Um eine Eigenschaft zu löschen: delete obj.prop
.
Um zu überprüfen, ob eine Eigenschaft mit dem angegebenen Schlüssel vorhanden ist: "key" in obj
.
So iterieren Sie über ein Objekt: for (let key in obj)
.
Was wir in diesem Kapitel untersucht haben, wird als „einfaches Objekt“ oder einfach nur Object
bezeichnet.
Es gibt viele andere Arten von Objekten in JavaScript:
Array
zum Speichern geordneter Datensammlungen,
Date
zum Speichern der Informationen über Datum und Uhrzeit,
Error
zum Speichern der Informationen zu einem Fehler.
…Und so weiter.
Sie haben ihre besonderen Eigenschaften, die wir später untersuchen werden. Manchmal sagt man so etwas wie „Array-Typ“ oder „Datumstyp“, aber formal sind sie keine eigenen Typen, sondern gehören zu einem einzigen „Objekt“-Datentyp. Und sie erweitern es auf verschiedene Weise.
Objekte in JavaScript sind sehr mächtig. Hier haben wir gerade erst an der Oberfläche eines wirklich großen Themas gekratzt. Wir werden in weiteren Teilen des Tutorials intensiv mit Objekten arbeiten und mehr über sie erfahren.
Wichtigkeit: 5
Schreiben Sie den Code, eine Zeile für jede Aktion:
Erstellen Sie ein leeres Objekt user
.
Fügen Sie den name
mit dem Wert John
hinzu.
Fügen Sie den surname
der Eigenschaft mit dem Wert Smith
hinzu.
Ändern Sie den Wert des name
in Pete
.
Entfernen Sie den name
vom Objekt.
let user = {}; user.name = "John"; user.surname = "Smith"; user.name = "Pete"; Benutzername löschen;
Wichtigkeit: 5
Schreiben Sie die Funktion isEmpty(obj)
, die true
zurückgibt, wenn das Objekt keine Eigenschaften hat, andernfalls false
.
Sollte so funktionieren:
let Schedule = {}; alarm( isEmpty(schedule) ); // WAHR Schedule["8:30"] = "aufstehen"; alarm( isEmpty(schedule) ); // FALSCH
Öffnen Sie eine Sandbox mit Tests.
Führen Sie einfach eine Schleife über das Objekt durch und geben Sie sofort return false
wenn mindestens eine Eigenschaft vorhanden ist.
Funktion isEmpty(obj) { for (obj eingeben lassen) { // Wenn die Schleife gestartet wurde, gibt es eine Eigenschaft return false; } return true; }
Öffnen Sie die Lösung mit Tests in einer Sandbox.
Wichtigkeit: 5
Wir haben ein Objekt, in dem die Gehälter unseres Teams gespeichert sind:
lass Gehälter = { Johannes: 100, Ann: 160, Pete: 130 }
Schreiben Sie den Code, um alle Gehälter zu summieren und in der Variablen sum
zu speichern. Sollte im obigen Beispiel 390
sein.
Wenn salaries
leer sind, muss das Ergebnis 0
sein.
lass Gehälter = { Johannes: 100, Ann: 160, Pete: 130 }; sei Summe = 0; for (Gehälter eingeben lassen) { Summe += Gehälter[Schlüssel]; } Warnung(Summe); // 390
Wichtigkeit: 3
Erstellen Sie eine Funktion multiplyNumeric(obj)
, die alle numerischen Eigenschaftswerte von obj
mit 2
multipliziert.
Zum Beispiel:
// vor dem Anruf let menu = { Breite: 200, Höhe: 300, Titel: „Meine Speisekarte“ }; multiplyNumeric(menu); // nach dem Anruf Menü = { Breite: 400, Höhe: 600, Titel: „Meine Speisekarte“ };
Bitte beachten Sie, dass multiplyNumeric
nichts zurückgeben muss. Es sollte das Objekt direkt ändern.
PS Verwenden Sie typeof
um hier nach einer Zahl zu suchen.
Öffnen Sie eine Sandbox mit Tests.
Funktion multiplyNumeric(obj) { for (obj eingeben lassen) { if (typeof obj[key] == 'number') { obj[Schlüssel] *= 2; } } }
Öffnen Sie die Lösung mit Tests in einer Sandbox.