JavaScript: Objekte

Objekte und Eigenschaften

Ein Objekt ist grob gesagt ein Bündel von Informationen im Speicher. Wie wir im Kapitel über Datentypen gelernt haben, unterscheidet JavaScript zwischen einfache Werten und Objekten. Manche einfache Werte können sich jedoch wie Objekte verhalten. Daher beschäftigt sich ein Großteil der JavaScript-Programmierung mit Objekten.

Ein Objekt funktioniert als eine Zuordnungsliste, die unter bestimmten Namen bestimmte Werte speichert. Dieses Name-Wert-Paar wird Eigenschaft genannt.

Ein Objekt, das eine Adresse speichert, könnte als Tabelle so aussehen:

Objekt »Adresse«
Eigenschaftsname Eigenschaftswert
name Erika Gabler
straße Königsallee 56
stadt 60322 Frankfurt

In einer Eigenschaft kann ein weiteres Objekt gespeichert sein. Durch diese Verschachtelung von Objekten entsteht eine beliebig lange Kette von Objekten, die aufeinander verweisen.

Der Browser stellt einem Script eine große Menge an vordefinierten Objekten zur Verfügung. Ein Script nutzt einerseits diese vordefinierten Objekte, indem es Eigenschaften ausliest und Methoden aufruft. Andererseits definiert ein Script eigene Objekte. Diese vom JavaScript-Programm selbst eingeführten Objekte werden üblicherweise in Variablen gespeichert.

Object-Literale

Die einfachste Art, in JavaScript ein Objekt zu erzeugen, ist der Object-Literal. Dieser fängt mit einer öffnenden geschweiften Klammer { an und endet mit einer schließenden }. Dazwischen werden die Eigenschaften mit Name und Wert aufgelistet. Zwischen Name und Wert steht ein Doppelpunkt, zwischen den Eigenschaften ein Komma. Das Schema sieht demnach so aus:

{
 name1: wert3,
 name2: wert2,
 name3: wert3
}

Die Anzahl der notierten Eigenschaften ist nicht begrenzt. Hinter dem letzten Name-Wert-Paar kann ein Komma notiert werden, aber es ist nicht nötig. Üblicherweise wird es weggelassen.

Das Adressen-Beispiel sieht in der Literalschreibweise so aus:

var adresse = {
  name: 'Erika Gabler',
  straße: 'Königsallee 56',
  stadt: '60322 Frankfurt'
};

Dies erzeugt ein Objekt mit drei Eigenschaften: name, straße und stadt. Alle drei Werte sind Strings. Als Tabelle könnte das Objekt so aussehen:

adresse

name"Erika Gabler"
straße"Königsallee 56"
stadt"60322 Frankfurt"

Der Object-Literal erzeugt ein allgemeines, unspezifisches Objekt ohne besondere Eigenschaften. Sie können es schnell erzeugen und darin beliebige Werte speichern. Später werden Sie kennenlernen, wie Sie eigene, spezifischere Objekt-Typen definieren.

Zugriff auf Eigenschaften

Ausgehend von einem Objekt können Sie auf dessen Eigenschaften zugreifen. Dazu notieren sie den Objektnamen, dann einen Punkt (.) und schließlich den Eigenschaftsnamen. Schematisch:

objekt.eigenschaft

Der Punkt (.) ist der Operator zum Zugriff auf Eigenschaften (englisch Property Accessor). Sowohl auf der linken als auch auf der rechten Seite des Punkts steht ein Bezeichner.

Ein Beispiel mit dem bekannten Objekt adresse:

var adresse = {
  name: 'Erika Gabler',
  straße: 'Königsallee 56',
  stadt: '60322 Frankfurt'
};
window.alert(
  'Der Name lautet: ' + adresse.name + '\n' +
  'Wohnhaft in: ' + adresse.straße + ', ' + adresse.stadt
);

Das Beispiel greift auf die drei Eigenschaften name, straße und stadt zu, um diese auszugeben. Dazu wird jeweils adresse.name, adresse.straße und adresse.stadt notiert.

Sie können den Operator zum Zugriff auf Eigenschaften auch mehrfach hintereinander verwenden. Auf diese Weise können Sie ganze Ketten an Eigenschaftsnamen notieren, um das gewünschte Objekt zu fassen zu bekommen:

window.location.href

In der fraglichen Eigenschaft wird Adresse (URL) des aktuellen Dokuments gespeichert.

Eine alternative Methode zum Ansprechen von Eigenschaften ist die Klammer-Schreibweise. Dabei wird der Eigenschaftsname zwischen eckigen Klammern als String notiert:

objekt["eigenschaft"]

Dies hat denselben Effekt wie objekt.eigenschaft. Der Vorteil dieser Schreibweise kommt dann zum Tragen, wenn der Name variabel ist und erst zur Laufzeit des Scriptes feststeht. Zwischen den Klammern lässt sich ein beliebiger Ausdruck notieren, also beispielsweise ein Variablenname:

objekt[variable]

Der JavaScript-Interpreter behandelt den Ausdruck als String und sucht nach einer entsprechenden Eigenschaft.

Mittels objekt.eigenschaft oder objekt["eigenschaft"] sprechen Sie eine Eigenschaft erst einmal an und bekommen eine sogenannte Referenz darauf. Je nachdem, wo Sie diesen Ausdruck verwenden, können Sie Verschiedenes mit der Referenz anfangen.

Bisher haben haben wir Eigenschaft gelesen. Schreiben Sie zum Beispiel window.alert(adresse.name), so wird der Eigenschaftswert gelesen und ausgegeben.

Wenn Sie den Wert einer Eigenschaft auslesen, die nicht existiert, bekommen Sie übrigens den Wert undefined zurück.

Sie können eine Eigenschaft auch schreiben. Dazu verwenden Sie den Zuweisungsoperator. Auf der linken Seite steht die Referenz, auf der rechten Seite der neue Wert:

adresse.name = 'Erika Mustermann geb. Gabler';

Falls die Eigenschaft bereits existiert, so wird der Wert geändert. Falls die Eigenschaft noch nicht existiert, wird sie automatisch angelegt, sofern es das Objekt zulässt.

Regeln und Konventionen für Eigenschaftsnamen

Ein Eigenschaftsname ist letztlich ein String und kann alle Zeichen enthalten, die in Strings möglich sind. Der Name bestimmt allerdings, mit welcher Methode Sie auf die Eigenschaft zugreifen können.

Üblicherweise wird die beschriebene Punkt-Schreibweise verwendet:

objekt.eigenschaft

Bei dieser Schreibweise gelten gewisse Regeln für den Eigenschaftsnamen. Es sind die gleichen Regeln, die auch für Bezeichner gelten. Eine genaue Beschreibung finden Sie dort.

Zusammengefasst: Der Eigenschaftsname darf nur aus Buchstaben, Dezimalziffern (0-9), dem Dollarzeichen ($) sowie dem Unterstrich (_) bestehen. Jedes dieser Zeichen darf an beliebiger Stelle vorkommen, mit Ausnahme der Ziffern, welche nicht an erster Stelle stehen dürfen.

Beispiele für mögliche Zugriffe auf Eigenschaften:

objekt.mitarbeiter_name
objekt.mitarbeiterName
objekt._mitarbeitername
objekt.$mitarbeitername
objekt.lohnIn$
objekt.mitarbeiter1
objekt.twenty4seven
objekt.größe

Beispiele für fehlerhafte Zugriffe auf Eigenschaften:

objekt.mitarbeiter name
objekt.mitarbeiter-name
objekt.lohnIn€
objekt.lohnIn£
objekt.2raumwohnung
objekt.ein♥FürTiere
objekt.arbeiter&angestellte

Wie gesagt bedeutet das nicht, dass Sie solche Eigenschaften nicht verwenden können. Sie können sie lediglich nicht über die Punkt-Schreibweise ansprechen, sondern müssen die Klammer-Schreibweise verwenden.

objekt["mitarbeiter name"]
objekt["mitarbeiter-name"]
objekt["lohnIn€"]
objekt["lohnIn£"]
objekt["2raumwohnung"]
objekt["ein♥FürTiere"]
objekt["arbeiter&angestellte"]

Nach Möglichkeit sollten Sie Eigenschaftsnamen verwenden, die den Regeln für Bezeichner entsprechen. Dann können Sie die gewohnte Punkt-Schreibweise verwenden, um auf sie zuzugreifen.

Methoden

Eine Eigenschaft kann einen beliebigen Wert haben. Alle Typen, die in JavaScript möglich sind, können in einem Objekt als Eigenschaft gespeichert werden.

Das heißt, an einem Objekt können auch Funktion hängen. Diese Eigenschaften werden dann Methoden genannt.

Ein Objekt kann also reine Daten speichern, aber auch eine Funktionalität besitzen, die zu diesen Daten gehört. Dies ist in der objektorientierten Programmierung häufig. Ein Beispiel:

var person = {
  vorname: 'Erika',
  nachname: 'Gabler',
  alter: 27,
  vollerName: function () {
    return this.vorname + ' ' + this.nachname;
  },
  istErwachsen: function () {
    return this.alter >= 18;
  }
};
window.alert( person.vollerName() );
window.alert( person.istErwachsen() );

Das Objekt person hat fünf Eigenschaften, davon sind zwei Methoden.

Um eine Methode zu erzeugen, verwenden Sie einen Funktionsausdruck function (…) {…} und notieren Sie ihn nach dem Doppelpunkt.

Innerhalb einer Methode haben Sie über das Schlüsselwort this Zugriff auf das Objekt, an dem die Funktion hängt. Dies funktioniert allerdings nur, wenn die Funktion mit dem üblichen Schema objekt.methode() aufgerufen wird.

Die Methoden vollerName und istErwachsen greifen auf die anderen Eigenschaften zu und machen etwas damit. vollerName verkettet die Eigenschaften vorname und nachname und gibt das Ergebnis zurück, ebenfalls ein String. istErwachsen prüft die Eigenschaft alter und gibt einen Boolean zurück.

Seit dem JavaScript-Standard ECMAScript 6 (2015) können Sie Methoden kompakter notieren:

var person = {
  vorname: 'Erika',
  nachname: 'Gabler',
  alter: 27,
  vollerName() {
    return this.vorname + ' ' + this.nachname;
  },
  istErwachsen() {
    return this.alter >= 18;
  }
};

Sie können den Doppelpunkt und das Schlüsselwort function weglassen und direkt mit der Parameterliste beginnen.

Konstruktoren, Prototypen und Instanzen

Ein JavaScript-Objekt gehört einem gewissen Typ an (siehe Datentypen). Diese Zugehörigkeit stellt sich in JavaScript so dar, dass ein Objekt von einer Funktion erzeugt wurde. Diese erzeugende Funktion wird Konstruktor genannt. Die meisten Konstruktor sind JavaScript-intern und vordefiniert, Sie können allerdings auch selbst definierte Funktionen als Konstruktoren verwenden.

Die Objekte, die ein bestimmter Konstruktor erzeugt hat, werden Instanzen (Exemplare) dieses Konstruktors genannt. Beispielsweise erzeugt ein Object-Literal eine Instanz des Konstruktors Object.

Jedes Objekt hat eine Eigenschaft namens constructor, die auf den Konstruktor verweist, der es hergestellt hat. Beispielsweise liefert adresse.constructor den Konstruktor Object.

Ein Konstruktor ist eine Art Fabrik, die Instanzen nach immer gleichem Muster produziert. Dieses Muster, der Bauplan für die Instanzen ist selbst ein Objekt: Das sogenannte prototypische Objekt, kurz Prototyp. Instanzen sind so gesehen Kopien des Prototypen und werden ihm nachgebildet.

Der Prototyp hängt an dem Konstruktor. Jede Funktion hat eine Eigenschaft namens prototype, die den zugehörigen Prototyp enthält. Object.prototype liefert beispielsweise das Objekt, das den Bauplan für alle Object-Instanzen definiert.

Jedes Objekt stammt also von einem Konstruktoren ab, dem ein Prototyp zugeordnet ist. Wenn wir ein Objekt erzeugen, dann wird entweder ausdrücklich oder hinter den Kulissen der entsprechende Konstruktor aufgerufen. Die Instanz erbt alle Eigenschaften des Prototypen. Dieser Vorgang wird prototypische Vererbung genannt.

Da Prototypen nur einfache Objekte sind, kann ein Prototyp auch selbst einen Prototyp haben und somit Eigenschaften erben. Auf diese Weise sind die Objekttypen voneinander ableitbar. Ein Date-Objekt beispielsweise ist gleichzeitig eine Instanz des Date-Konstruktors als auch eine Instanz des obersten Object-Konstruktors.

Der Prototyp ist ein ganz normales JavaScript-Objekt, dem Sie neue Eigenschaften hinzufügen können. Auf diese Weise können alle Instanzen, die vom fraglichen Prototypen erben, auf einen Schlag mit neuen Fähigkeiten ausgestattet werden. Diese Methode nennt sich prototypische Erweiterung.

Dass beim Erstellen eines Objekts ein Konstruktor aufgerufen wird und der Prototyp als Bauplan für das Objekt dient, immer nicht immer offensichtlich. Das Wissen um Konstruktoren und Instanzen ist jedoch notwendig, wenn wir in diese Vorgänge eingreifen oder eigene Konstruktoren und Prototypen schreiben wollen. Näheres dazu finden Sie im Kapitel Organisation von JavaScripten: Konstruktoren, Prototypen und Instanzen.

Objekte erzeugen: Literale und Instantiierung

Objekte können in JavaScript auf zwei Weisen erzeugt werden: Durch einen Literal oder das ausdrückliche Erzeugen einer Instanz mit dem Schlüsselwort new.

Ein Literal ist eine Kurzschreibweise, mit der Sie Werte am schnellsten notieren können. Wir haben den Object-Literal {…} kennengelernt. Dieser erzeugt ein Objekt vom Typ Object.

Die Langschreibweise erzeugt ein Objekt, indem es einen Konstruktoren mit new aufruft. Um beispielsweise ein Object zu erzeugen, können wir new Object() schreiben. Das heißt, folgende Schreibweisen sind identisch:

// Object-Literal
var person1 = { name: 'Erika Gabler' };

// Instanz von Object mit 'new' erzeugen
var person2 = new Object();
person2.name = 'Erika Gabler';

Nicht alle Objekttypen lassen sich auf beide Weisen erzeugen. Wenn eine Literalschreibweise für den gewünschten Objekttyp existiert, dann sollten Sie diese auch nutzen. Für manche Objekttypen existiert keine Literalschreibweise.

Für Arrays beispielsweise gibt es eine Literalschreibweise: […]. Ebenso für für reguläre Ausdrücke: /…/. Es gibt allerdings kein Literal, um ein Datum zu erzeugen. Sie müssen new Date() notieren.

Das globale Objekt window