AJAX - Frische Ansätze für das Web-Design

3.2 Objektbasierte Programmierung

JavaScript (bzw. der Sprachkern ECMAScript) ist eine objektbasierte Sprache, d. h. sie kennt zwar Objekte, beinhaltet aber kein Klassenkonzept wie es aus objektorientierten Programmiersprachen wie z. B. C++ und Java bekannt ist. Jedoch gibt es auch in JavaScript Konstruktoren, die Objekte erzeugen, indem sie Speicherplatz dafür reservieren und die Eigenschaften neuer Objekte mit Anfangswerten initialisieren. Anders als bei klassenbasierten Sprachen können einem Objekt jedoch auch nach seiner Instantiierung noch weitere Eigenschaften hinzugefügt werden - dies geschieht, indem man diesen einfach Werte zuweist.

Eine weitere Besonderheit von JavaScript ist, dass ein Konstruktor selbst auch ein Objekt ist. Ein Konstruktor verfügt insbesondere über eine Eigenschaft namens prototype. Dieser Prototyp eines Konstruktors ermöglicht eine spezielle Art der Vererbung und fasst gemeinsame Eigenschaften von Objektinstanzen zusammen.

Die prototypbasierte Vererbung in JavaScript basiert darauf, dass jedes neu erzeugte Objekt eine implizite Referenz auf den Prototyp seines Konstruktors besitzt. Eine mehrstufige Vererbung ist dadurch möglich, dass der Prototyp eines Objekts selbst wieder eine Referenz auf einen weiteren Prototypen besitzen kann. So kann eine Kette von Prototypen entstehen, die zu den Eigenschaften eines Objekts beitragen. Wird in einem Objekt eine Eigenschaft referenziert, die es in diesem Objekt selbst nicht gibt, so wird diese Eigenschaft als nächstes im Prototyp des Objekts gesucht. Ist die gesuchte Eigenschaft auch dort nicht definiert, so wird die Suche entlang der Prototypenkette fortgesetzt, bis eine Eigenschaft mit dem entsprechenden Namen gefunden wird oder das Ende der Kette erreicht ist.

So wird bei der Vererbung in JavaScript nicht nur (wie in klassenbasierten Sprachen) eine Struktur vererbt, sondern ein neues Objekt erbt auch den Zustand und alle Methoden seines Prototyps.

Etwas verwirrend dabei ist, dass der Prototyp eines Objektes eine implizite Eigenschaft ist (die allerdings bei einigen Browsern über den Namen __proto__ ansprechbar ist). Diese implizite Eigenschaft wird bei der Erstellung des Objektes durch new mit dem gegenwärtigen Wert der Eigenschaft prototype des Konstruktors besetzt. Will man später noch einmal auf den Prototyp eines Objektes zugreifen, so geht das (außer über die nicht standardisierte Eigenschaft __proto__) nur über das Konstruktor-Objekt und seine Eigenschaft prototype.

Sehen wir uns dazu ein einfaches Beispiel an:

function ObjektA() {
}
ObjektA.prototype = {
  text: "Dieses Objekt basiert auf ObjektA",
  zahl: 99
};
function ObjektB(z) {
  this.zahl = z;
}
ObjektB.prototype = new ObjektA();

Hier werden Konstruktoren für zwei Objekte ObjektA und ObjektB definiert. Der Konstruktor von ObjektA nimmt dabei keine besonderen Initialisierungen vor, allerdings besitzt ObjektA als prototype-Eigenschaft ein Objekt mit zwei Eigenschaften, text und zahl (dieses Objekt wird mit einem Objektinitalisierer hergestellt: zwischen geschweiften Klammern stehen durch Komma getrennte Paare der Form Name: Wert). Die Eigenschaft prototype von ObjektB verweist auf eine Instanz von ObjektA, so dass dessen Eigenschaften von allen mit dem Konstruktor ObjektB erzeugten Objekten geerbt werden. Jede Instanz von ObjektB erhält durch ihren Konstruktor darüber hinaus eine eigene Eigenschaft mit dem Namen zahl, deren Wert aus dem Argument des Konstruktors stammt. Erzeugen wir nun einige Instanzen dieser beiden Objekte:

var a1 = new ObjektA();
var a2 = new ObjektA();
var b = new ObjektB(22);

Wird nun a1.text, a2.text oder b.text referenziert, so bezieht sich das jeweils auf die Eigenschaft text des Prototypobjekts von ObjektA. Man erhält dafür also in allen drei Fällen den Wert Dieses Objekt basiert auf ObjektA. Auch mit dem Referenzieren von a1.zahl und a2.zahl erhält man den entsprechenden Wert (99) aus dem Prototypobjekt. Dagegen ist b.zahl die Eigenschaft zahl in der erzeugten Instanz von ObjektB und hat den Wert 22 - die gleichnamige Eigenschaft des Prototypobjekts wird hier also verdeckt. JavaScript-Objekte und Prototypen illustriert die Beziehungen der Objekte zueinander.

Abb 19 JavaScript-Objekte und Prototypen

Weisen wir nun in einer der Instanzen von ObjektA der Eigenschaft zahl einen neuen Wert zu:

a1.zahl = 77;

Nach dieser Zuweisung besitzt die Instanz a1 nun eine eigene Eigenschaft namens zahl, die den Wert 77 hat. Für die andere Instanz des Objekts, a2, ergibt sich dadurch aber keine Änderung. In ihr gibt es nach wie vor keine Eigenschaft zahl, so dass beim Referenzieren von a2.zahl noch immer auf die entsprechende Eigenschaft des Prototypobjekts mit dem Wert 99 zugegriffen wird. Wir können aber nicht nur Eigenschaften einzelner Instanzen einen Wert zuweisen, sondern auch Eigenschaften eines Prototypobjekts ändern:

ObjektA.prototype.text = "Neuer Text";

Da keine der Instanzen a1, a2 und b, die (direkt oder indirekt) auf dem Prototyp von ObjektA basieren, eine eigene Eigenschaft namens text hat, wirkt sich diese Änderung auf alle drei Instanzen aus. Beim Referenzieren von a1.text, a2.text oder b.text erhält man nun also jeweils den neuen Wert der Eigenschaft im Prototypobjekt von ObjektA, also Neuer Text. Solange den Instanzen nicht selbst eine gleichnamige Eigenschaft zugewiesen wird, verfügen sie hier also über eine gemeinsame Eigenschaft, deren Wert sich mit Wirkung für alle Instanzen zugleich ändern lässt. (Ebenso könnte man ObjektA.prototype auch eine neue Eigenschaft geben, die dann sofort als Eigenschaft der drei Objekte a1, a2 und b sichtbar würde.)

Kommentare (0)

Ihr Kommentar

Name