Benutzer:Rolf b/Objekte

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Objekte

Um ein Objekt benutzen zu können, muss man es zuerst einmal erzeugen. Eine Möglichkeit dafür ist der new-Operator:

Beispiel

Erzeugen eines Objekts

const personA = new Object();
In personA ist nun ein Objekt gespeichert! Noch ist es leer, aber wir können ihm Eigenschaften zuweisen.
personA.name = "Ann";
personA.age  = 31;
Das neue Objekt hat nun zwei Eigenschaften bekommen: name, mit der Zeichenkette "Ann" als Wert, und age, mit dem Wert 31.

Objekteigenschaften sind Variablen ähnlich. Der Unterschied ist der Ort, wo sie gespeichert sind. Während Variablen im Gültigkeitsbereich (Scope) einer Funktion gespeichert werden, und genauso lange existieren wie dieser Scope, werden Objekteigenschaften im Objekt abgelegt und existieren so lange wie dieses Objekt.

Dass Sie eine Objekteigenschaft verwenden wollen, und nicht eine Variable, wird durch die Punkt-Notation (dot-syntax) erkennbar. Links vom Punkt steht das Objekt und rechts davon der Name der gewünschten Eigenschaft. Wie bei einer Variablen bedeutet Notierung links von einem Gleichheitszeichen, dass ein Wert zugewiesen werden soll. Und wie bei einer Variablen bedeutet die Notierung an anderer Stelle, dass der gespeicherte Wert verwendet werden soll.

Die Ähnlichkeit mit Variablen geht auch dahingehend weiter, dass für die Namen von Eigenschaften, die mit der Punkt-Notation zugewiesen oder ausgelesen werden, die Regeln für selbstvergebene Namen gelten.

Hinweis:
personA wurde als const deklariert. Man könnte daraus folgern, dass das Objekt dadurch unveränderbar ist. Das ist ein Missverständnis. Die const-Angabe gilt nur für personA selbst, eine Zuweisung dorthin ist nicht möglich. Für das, was in personA gespeichert wurde, gilt die const-Deklaration aber nicht. Befindet sich dort ein Array oder ein Objekt, ist es frei änderbar. Eine Schreibschutz für das Objekt selbst könnte mit Object.freeze() oder Object.seal() herbeigeführt werden. Ob Sie eine Variable, die ein Objekt speichern soll, mit const oder let deklarieren, ist Ihre Entscheidung. Die Entscheidung für die Art der Deklaration unterliegt den gleichen Kriterien wie bei anderen Variablen. Wird der Variablenwert nur einmal zugewiesen und nicht mehr geändert, empfehlen wir Ihnen die Verwendung von const.

Weitere Wege zu neuen Objekten

Es gibt mehrere Wege, ein Objekt zu erzeugen. Den ersten Weg haben Sie bereits gesehen. Was eine Konstruktorfunktion ist, wird etwas später erklärt.

  • mit dem Schlüsselwort-Operator new und dem Namen einer Konstruktorfunktion
  • durch ein Objektliteral (literal - engl. für wörtlich)
  • mit der Methode Object.create()

Der Begriff „Literal“ ist in der Programmierung für feste Werte üblich, die im Programmcode notiert werden. Schauen Sie sich den Unterschied zwischen den new-Operator und einem Objektliteral an:

Erzeugung mit Schlüsselwort "new"
const personA = new Object();
personA.name   = 'Ann';
personA.age    = 31;
personA.adult  = true;
Erzeugung in Literalschreibweise
const personB = {
    name:  "Bob",
    age:   29,
    hobby: "drinking"
};

Auf eine Besprechung von Object.create() kommen wir später zurück.

Objektliterale sind ähnlich wie der Eigenschaftenteil einer CSS Regel aufgebaut. Das Literal ist in geschweifte Klammern eingeschlossen, und darin werden die gewünschten Eingeschaften aufgelistet. Anders als in CSS werden sie durch ein Komma voneinander abgegrenzt (weil das Semikolon in JavaScript dazu da ist, ein Statement zu beenden). Jede Eigenschaft besteht aus einem Namen, einem Doppelpunkt und dem Wert, den die Eigenschaft haben soll.

Jetzt haben Sie also zwei Objekte, die in personA und personB gespeichert sind. Beiden gemeinsam sind die Eigenschaften name und age. Sie unterscheiden sich ein wenig, bei Ann ist noch eine Eigenschaft adult mit dem booleschen Wert true angelegt worden, während Bob ein Hobby zugewiesen wurde.

Hinweis:
Die Literalschreibweise ist immer dann nützlich, wenn Sie ein einfaches Objekt gut lesbar in einem Zug erzeugen und initialisieren wollen. Deshalb spricht man auch von einem Objektinitialisierer.

Eigenschaften untersuchen

Schauen Sie sich einmal an, wie sich ein Objekt in den Entwicklerwerkzeugen Ihres Browsers darstellt. Sollten Sie das Wiki mit einem Handy lesen, müssten Sie dafür bitte auf ein Desktopgerät wechseln oder sich mit den Screenshots zufrieden geben, denn die Mobilbrowser haben diese Funktion nicht.

Zeigen Sie sich für das folgende Beispiel bitte die Vorschau an und öffnen Sie dann die Entwicklerwerkzeuge des Browser. Dazu verwenden Sie entweder die Funktionstaste F12, die Tastenkombination Strg+I oder klicken Sie mit der rechten Maustaste in die Vorschau und wählen den Menüpunkt "Untersuchen". Die Entwicklerwerkzeuge können sich in einem neuen Fenster öffnen, oder als ein Ausschnitt dieses Fensters. Suchen Sie darin nach einem Abschnitt mit der Bezeichnung "Konsole" oder "Console" und wählen Sie ihn aus.

Untersuchung mit Console API ansehen …
const personB = {
    name:  "Bob",
    age:   29,
    hobby: "drinking"
};
    
console.log(personB.name);
console.log(personB.hasOwnProperty("age"));
console.log(personB);

Dieses erste Live-Beispiel wiederholt den vorhin vorgestellten Code:

  • Mit der Literalschreibweise wird ein Objekt erzeugt und als Konstante personB gespeichert.
  • Das console-Objekt ist eine Testhilfe, die der Browser bereitstellt. console.log ist eine Objekteigenschaft, in der eine Funktion gespeichert ist. Diese Funktion gibt die Werte, die Sie ihr übergeben, im Konsolenfenster der Entwicklerwerkzeuge aus.
  • Im ersten Aufruf von console.log wird die name-Eigenschaft des Objekts in personB ausgelesen und der Wert ausgegeben.
  • Im zweiten Aufruf wird mittels hasOwnProperty("age") überprüft, ob eine Eigenschaft mit diesem Namen existiert. Auf hasOwnProperty kommen wir gleich noch zurück.
  • Der dritte Aufruf bekommt das komplette Objekt aus personB übergeben. Was da wohl passieren mag?

In der Konsolenausgabe sollten Sie etwas finden, das so oder ähnlich aussieht. Das Bild zeigt die Darstellung im Firefox-Browser. Andere Browser zeigen in der dritten Zeile möglicherweise nur ▶ Object.

OOP-1.png

Sie sehen die Ausgabe des Namens Bob, das Ergebnis true der hasOwnProperty-Abfrage und eine kompakte Darstellung des Objekts. Klicken Sie nun auf das graue Dreieck vor Object. Damit erhalten Sie eine Detailansicht des Objekts.

OOP-2.png

Zusätzlich zu ▶ Object finden Sie nun jede Eigenschaft des Objekts in einer eigenen Zeile, und darunter etwas merkwürdiges: <prototype>: Object { ... }. Statt der spitzen Klammern verwendet Ihr Browser möglicherweise zwei eckige Klammern. Vor der prototype-Zeile ist wieder ein schwarzes Dreieck. Das ist also ebenfalls ein Objekt - schauen Sie es sich an. Sie werden einige Eigenschaften finden, bei denen function (oder nur f) als Wert angegeben ist, darunter befindet sich auch die Funktion hasOwnProperty, die Sie vorhin schon im Einsatz gesehen haben. Auf Prototypen und ihre Bedeutung kommen wir später zurück, aber offenbar fügen sie einem Objekt Funktionalität hinzu.

Es gibt mehrere Möglichkeiten, wie Sie die Eigenschaften eines Objekts ermitteln können:

  • for...in: Schleife, durchläuft alle aufzählbaren Eigenschaften eines Objekts und seiner Prototypenkette
  • Object.keys(): gibt einen Array mit allen aufzählbaren Eigenschaftsnamen aus
  • Object.getOwnPropertyNames(): gibt einen Array mit allen Eigenschaftsnamen aus

Eigenschaften indirekt ansprechen

Wenn Sie sich schon mit Arrays beschäftigt haben, dann werden Sie wissen, dass man auf ein Element eines Arrays nicht nur mit einem festen Index zugreifen kann. Dieser Index kann auch zur Programmlaufzeit berechnet werden und sich in einer Variablen befinden.

Objekte bieten eine vergleichbare Möglichkeit. Allerdings kann die bisher vorgestellte Punkt-Notation dafür nicht genutzt werden, denn sie erwartet einen festen Eigenschaftsnamen. Statt dessen wurde für diesen Zweck die von Arrays bekannte Klammer-Notation auf Objekte übertragen.

Zugriff auf Objekteigenschaften über eine Variable
const personC = {
   name: "Cem",
   alter: 2,
   hobby: "nuckeln"
};

const eig = "hobby";
if (personC.hasOwnProperty(eig)) {
   let wert = personC[eig];
   console.log(`${personC.name} hat die Eigenschaft ${eig} mit dem Wert ${wert}`);
}

Der Wert, der an console.log übergeben Rückgabewert der Funktion im Beispiel ist ein Template-Literal, dessen String innerhalb der Backticks `…` noch in ${…} eingeschlossene JavaScript-Ausdrücke, nämlich die Eigenschaften name und age enthält.

Methoden

Objekte können nicht nur irgendwelche Daten als Eigenschaften haben, sondern auch Funktionalitäten speichern. Diese Funktionalitäten werden im Grunde wie reguläre Funktionen definiert, sind als Eigenschaft eines Objektes gespeichert, was zusätzliche Möglichkeiten bringt. Man spricht in diesem Fall von Methoden.

Hinweis:
Methoden sind auch nur Eigenschaften eines Objektes, aber ihr Wert ist eben ein Funktionsobjekt.


Methode sayName() ansehen …
personA.sayName = function () {
      return `My name is ${personA.name} and I am ${personA.age}!`;
    }
    
const personB = {
    name:  "Bob",
    age:   29,
    hobby: "drinking",
    sayName () {
      return `My name is ${personB.name} and I am ${personB.age}!`;
    }
}
    
console.log(personA.sayName());
console.log(personB.sayName());

Beide Objekte enthalten nun eine Eigenschaft sayName, der aber kein Wert, sondern eine Funktion zugewiesen ist. Diese Funktion lässt sich wie jede andere auch aufrufen.

Der Rückgabewert der Funktion im Beispiel ist ein Template-Literal, dessen String innerhalb der Backticks `…` noch in ${…} eingeschlossene JavaScript-Ausdrücke, nämlich die Eigenschaften name und age enthält.




Beide Funktionen beziehen sich auf Eigenschaften ihres Objekts. Könnte man dies nicht klarstellen, ohne jeweils den Namen des Objekts nennen zu müssen? So wie in der Sprache ein Pronomen auf ein Objekt oder eine Person zeigt?