Web Development

Ein Lehrbuch für das Informatik oder Medien-Informatik Studium.

Hinter den “Klassen” von Javascript versteckt sich in Wirklichkeit an anderer Mechanismus: Prototypen.

Objekt und Konstruktor und Prototyp

Wie im vorigen Kapitel kurz erläutert ist jede Funktion in Javascript auch ein Objekt. Man kann zur Funktion Attribute speichern. Es gibt ein Attribut mit einer speziellen Bedeutung bei einer Konstruktor-Funktion: das Attribut prototype: prototype verweist auf ein Objekt, in dem weitere Methoden und Attribute für alle Objekte die mit diesem Konstruktor erzeugt wurden gespeichert werden.

Javascript Code Methoden und Attribute definieren mit dem Prototyp

// Konstruktor
function Studiengang(name, seit, hs) {
  this.name = name;
  this.seit = seit;
  this.hs = hs;
}
// Zwei Attribute am prototyp des Konstruktors
Studiengang.prototype.min = 2;
Studiengang.prototype.max = 42;
// Eine Methode am prototyp des Konstruktors
Studiengang.prototype.toString = function () {
  return "Studiengang " + this.name + 
    " (seit " + this.seit + 
    " @ " + this.hs.name + ")";
}

typeof Studiengang;  // function! 

mmtb = new Studiengang( "BSc MultiMediaTechnology", 2008, hs );
mmtm = new Studiengang( "MSc MultiMediaTechnology", 2011, hs );

mmtb.toString();  // findet toString Methode des 
            // Prototypen und ruft sie auf

mmtb.min    // findet min Attribut des Prototypen
            // gibt Wert 2 
mmtb.min=5  // speichert Wert 5 im Objekt selbst
mmtb.min    // gibt jetzt Wert 5
mmtm.min    // findet min Attribut des Prototypen, 
            // gibt Wert 2 

Demo mit Visualisierung

Wird ein Attribut oder eine Methode an einem Objekt gesucht, und kann direkt am Objekt nicht gefunden werden, dann durchsucht der Javascript-Interpreter als nächstes den Prototypen des Konstruktors.

Attribute direkt im Objekt überschreiben die Attribute des Prototypen: im Beispiel wird das Attribut min direkt im Objekt gefunden, hier ist kein Zugriff auf den Protypen nötig.

Abbildung: Objekt mit Konstruktor

Vertiefung

Dies war nur ein erster Einstieg in die objektorientierte Programmierung mit Javascript. Details zu einigen wichtigen Befehlen in der Javascript-Referenz bei Mozilla:

Vererbung

Eine Konstruktur-Funktion kann von einem Objekt erben, und zwar über den Prototypen:

Javascript Code Vererbung von Attributen

  // ----- Pet ---------
  function Pet() {
    this.status = "sleeping";
  }
  Pet.prototype.log = function() {
    console.log("i am " + this.status + 
      ". " + this.word + "!");
  }

  // ----- Mammal ---------
  function Mammal() {
    this.legs = 4;
  }
  Mammal.prototype = new Pet();
  Mammal.prototype.constructor = Mammal;

  // ----- Dog --------
  function Dog( b ) {
    this.breed = b;
    this.word = "wau";
  }
  Dog.prototype = new Mammal();
  Dog.prototype.constructor = Dog;

  Dog.prototype.sit = function() {
    this.status.set("sitting");
  }

  d = new Dog("beagle");
  d.word    // direkt im Objekt gespeichert
  d.legs    // im Prototyp von Dog gespeichert 
            // (einem Mammal-Objekt)
  d.status  // im Prototyp von mammal gespeichert 
            // (einem Pet-Objekt)

Demo mit Visualisierung

Diese Vererbungs-Kette über die Prototypen nenn man auf english “prototype chain”.

Achtung: die Konstruktoren der übergeordenten Objekte werden nur einmal aufgerufen, das kann zu unerwarteten Effekten führen:

Javascript Code Vererbung von Attributen

  // ----- Pet ---------
  function Pet() {
    this.status = new Status();
  }
  // ....
  Mammal.prototype = new Pet();
  // ....
  d1 = new Dog("Beagle");
  d2 = new Dog("Schnauzer");
  
  d1.status === d2.status // es gibt nur ein Status-Objekt 
                          // für alle Mammals!
  d1.hasOwnProperty('status'); // false

  d1.status = new Status('playing');

  d1.status === d2.status      // false
  d1.hasOwnProperty('status'); // true

Das Wunder des dreibeinigen Hundes

Der Schnauzer hat einen schrecklichen Unfall, und verliert ein Bein:

Javascript Code Vererbung von Attributen

d1 = new Dog("Beagle");
d2 = new Dog("Schnauzer");
d2.legs = 3;

console.log(d1.legs); // 4 Beine von Mammal
console.log(d2.legs); // 3 Beine 

d1.hasOwnProperty('legs') // ... false
d2.hasOwnProperty('legs') // ... true

Doch nun geschieht ein Wunder: wenn wir mit delete das Attribut legs aus d2 entfernen hat er wieder 4 Beine - weil das im prototypen so gespeichert ist.

Javascript Code Vererbung von Attributen

delete(d2.legs);

console.log(d2.legs);     // 4 Beine 
d2.hasOwnProperty('legs') // ... false