Verfasst von: bletra | 17. November 2009

JavaScript: Vererbung

JavaScript ist eine funktionale Sprache, es gibt aber auch Objekte und eine Art Vererbung – die Programmiererin muss selbst darauf achten, gewisse Dinge einzuhalten oder sich entsprechende Hilfsfunktionen definieren oder noch besser, gleich ein geeignetes Framework einsetzen. Hier möchte ich auf die einfachste Vererbung in JavaScript eingehen – Frameworks kommen später 😉

Im einfachsten Fall habe ich also eine Objektschablone Animal und eine davon erbende Objektschablone Dug.

function Animal(name, outputId) {
  /* public */
  this.Name = name;
  this.OutputNode = document.getElementById(outputId);
}
function Dug(name, outputId) {
...
}
Dug.prototype = new Animal();

Durch die außerhalb der Vorlage Dug angegebene Anweisung Dug.prototype = new Animal(); findet die Vererbung statt. Genauer gesagt erhält die Objektschablone Dug einen Link auf die Objektschablone Animal. Der Konstruktor, d.h. die Funktion Animal wird damit ausgeführt und Dug hat die öffentlichen Eigenschaften Name und OutputNode. Ich sehe in diesem Ansatz folgende Nachteile:

  • Die Parameter name, outputId können nicht direkt an den Konstruktor der Superklasse Animal übergeben werden.
  • Prinzipiell kann jede von außen die Schablone Dug oder Animal verändern. Dies kann auch für einzelne Instanzen erfolgen:
    • var donald = new Dug(); donald.Hello = function() {alert(‚Hello‘);} //nur die Instanz donald kennt Hello
    • Dug.prototype.Fly = „Ich fliege“; //alle Instanzen von Dug haben nun die Eigenschaft Fly

Am zweiten Problem kann man nichts ändern, dies ist „by Design“, also so gewollt. Für das Konstruktorproblem gibt es zwei Ansätze:

  1. Einführung einer öffentlichen Eigenschaft, die auf die Superklasse zeigt.
  2. Verwendung von .constructor

Für beide Varianten, auch wenn Variante 1 vielleicht anderes suggeriert,  bleibt die Anweisung außerhalb der Objektschablonen
Dug.prototype = new Animal();  zur Definition der Vererbung notwendig.

Variante 1:

<pre>function Dug(name, outputId) {
  this.base = Animal; //Zeiger auf Definition Animal, base ist ein frei wählbarer Bezeichner
  this.base(name, outputId);
...

Ich muss also zweimal definieren, dass Animal meine Superklasse sein soll, hm.

Variante 2:

function Dug(name, outputId) {
  this.constructor(name, outputId);
...

Eigentlich ziemlich genau, was ich möchte, wenn auch nicht unbedingt intuitiv. ABER, wenn ich nun vergesse, mit Dug.prototype = new Animal(); die Vererbung zu deklarieren, dann wird nicht, wie ich es vermutet hätte, der Konstruktor von Object ausgeführt, sondern der tatsächliche Konstruktor, nämlich Dug. Man landet dann in einer Endlosschleife. Warum? Für jede Objektschablone, erzeugt JavaScript, per default, folgende Definition:

  Dug.prototype = new Object();
  Dug.prototype.constructor = Dug; //alle Instanzen von Dug haben nun die Eigenschaft .constructor = Dug!

Erst das Überschreiben von prototype überschreibt auch den Konstruktor entsprechend.

Fazit

Es gibt Vererbung in JavaScript. Wenn ich jedoch tatsächlich mehrere von einander erbender Objekte brauche, dann werde ich Hilfsfunktionen wie bei MooTools oder anderen implementieren, die mir die Fehlerwahrscheinlichkeit reduzieren. Zu MooTools gibt es eine gute Einführung von Peter Kröner. Es lohnt sich auch, den Quellcode von MooTools anzusehen!!!


Hinterlasse einen Kommentar

Kategorien