JavaScript [Prototype] Kann mir bitte jemand die Vererbungslogik sinnvoll erklären?

T

Tersus

Gast
Guten Tag,

vorweg: falls jemand für mich googeln will, ist nicht nötig, das kann ich selber. Es gibt zum Thema Prototypen dutzende Tutorials und ich habe sicher schon 6 davon intensiv durch. :freak:
Ich, als jemand, der klassenorientierte Programmierung vollständig beherrscht, blicke absolut nicht durch, was die Vererbung in JavaScript betrifft. Ich weiß nicht, warum ich mich so schwer damit anstelle.

Laut aller Tutorials verweißt der Prototyp eines Objekts auf sein darüber liegendes Objekt. Entspricht also eine super in Java.

Ich stelle mir das wie eine verkette Liste vor. Eine Katze ist ein Tier und erbt entsprechend von Tier. Ein Tier ist ein Lebewesen und erbt entsprechend von Lebewesen. Der JavaScript Vererbungsbaum müsse so aussehen:

[Katze] --> [Tier] --> [Lebewesen]

Der Prototyp von [Katze] ist also [Tier] und dessen Prototyp ist [Lebewesen]. Der Prototyp von Lebewesen ist [Object] und dessen Prototyp ist null, weil es die oberste "Klasse" ist.


Ich greife mal folgendes Tutorial auf: http://blog.mayflower.de/4451-JS-Vererbung-Prototypen.html

In diesem Beispiel soll der [Customer] vom [User] erben.
[User] sieht so aus.
Code:
var User = function () {};
 
User.prototype.setIp = function (ip) {
  this.ip = ip;
};
 
User.prototype.setLastVisit = function (date) {
  this.lastVisit = date;
};

Hier sind viele Sachen für mich total missverständlich!

Wir greifen auf den Prototypen von [user] zu. Das ist doch im Moment [object]? Also weisen wir die Funktionen "setIp" und und "setLastVisit" [object] zu ...

Meines Irrwissens nach müsste die Klasse so aussehen:

Code:
function User() {

  this.setIp = function (ip) {
    this.ip = ip;
  };
 
  this.setLastVisit = function (date) {
    this.lastVisit = date;
  };

};


Als nächstes folgt aus dem Tutorial die Klasse [Customer]. Diese ist auch meinem Irrwissen nach fast richtig aufgebaut.

Code:
var Customer = function (name, email) {
  this.name = name;
  this.email = email;
};

Ich verstehe nicht, wieso der Kopf nicht so function Customer( ... ){ ... } aussieht.

Zuletzt aus dem Tutorial die Vererbungssetzung:

Code:
Customer.prototype = new User();
Customer.prototype.constructor = Customer;

Zeile 1. verstehe ich so, dass der Prototyp von [Customer], also das Oberobjekt, nun auf [User] gesetzt wird.
Die Zeile 2. ist schon wieder komisch. Wir greifen auf den Konstruktor des Prototypen von [Customer], also den Konstruktor von [User], zu und weisen ihm das Objekt [Customer] zu!? Customer.constructor hätte ich noch ansatzweise akzeptiert, aber so ist das doch totaler unverständlich ... :freak:
Weiterhin wird die Vererbung erst nach dem Objektrumpf zugewiesen! Wie soll man dann den Konstruktor der "Oberklasse" aufrufen um an ihn die Parameter weiterzureichen!?

Im Moment ist JavaScript für mich total abartig. :(

Ich danke demjenigen vielmals, der sich meinem Problem annimmt und es mir so erklärt, dass ich es verstehe.
 
Laut aller Tutorials verweißt der Prototyp eines Objekts auf sein darüber liegendes Objekt. Entspricht also eine super in Java.
Es wird immer erst im eigenen Objekt geprüft ob die Methode oder Eigenschaft verfügbar ist. Danach wird die Prototypenkette analysiert. Zuerst der eigene und dann wird die Kette noch oben geprüft.

Wir greifen auf den Prototypen von [user] zu. Das ist doch im Moment [object]? Also weisen wir die Funktionen "setIp" und und "setLastVisit" [object] zu ...
Nein es wird auf den eigenen Prototypen zugegriffen. Das wichtige fehlt hier leider im Codebsp.
Denn anders als bei einen Funktions- / Methodenaufruf wird bei einer Konstruktorfunktion(aufgerufen mit new) ein neues Objekt erstellt. Hierbei wird this an das neue Objekt gebunden und implizit als Ergebnis zurückgegeben (kein return im Konstruktor notwendig).

Meines Irrwissens nach müsste die Klasse so aussehen:
In dem Beispiel werden die Methoden in das Eigene Objekt geschrieben.

Als nächstes folgt aus dem Tutorial die Klasse [Customer]. Diese ist auch meinem Irrwissen nach fast richtig aufgebaut.

Es fehlt noch User.call(this, weitere Paramater)

Die Zeile 2. ist schon wieder komisch. Wir greifen auf den Konstruktor des Prototypen von [Customer], also den Konstruktor von [User], zu und weisen ihm das Objekt [Customer] zu!?
Die Vererbst den Prototypen von User und musst den Konstruktor neu setzen!
Customer.prototype.constructor ist ohne die Zeile dann User und nicht wie gewünscht Customer.
 
Zuletzt bearbeitet:
Ich hab auch etwas Zeit gebraucht um die JS Vererbung so richtig zu raffen. Das Prinzip ist sehr leicht, nur macht es JS im Code tweiweise unnötig Verwirrend. So etwa habe ich es gerafft:
Mein Tipp: Google mal nach Object.create(), vergiss "new" und "Klassen" mal komplett! Vererbung in JS besteht eben nur aus "Ketten" von Objekten. Keine Klassen!
Bei Objekten kann die interne Eigenschaft [[Prototype]] auf ein anderes Objekt zeigen, von dem dann geerbt wird. (Die Notation mit [[bla]] verwendet der JavaScript Standard. Das bedeutet auf die Eigenschaft bla kann man nicht direkt zugreifen, sondern sie existiert nur intern im JS Compiler)

Code:
var a = Object.create(null);
a.foo = "hallo";
var b = Object.create(a);
b.foo; // => "hallo"
var b2 = Object.create(a);
b2.foo; // => "hallo"
a ist jetzt ein ein Objekt, welches von null erbt. Es ist also komplett "leer". [[Prototype]] von a ist null.
[[Prototype]] von b zeigt auf a. b erbt also von a. Vom Schema her so:
-> [a] -> null

b2 erbt auch von a. Deswegen macht man Vererbung überhaupt. Viele Objekte können von einem Prototyp erben. Das spart Code und Arbeitsspeicher, denn man hat immer nur Referenzen.
Ganz simpel. So geht Vererbung. Nicht vergessen.
Mal so zum Verständnis:
Code:
var o = Object.create(Obejct);
// ist übrigens genau das Gleiche wie:
var o = {}; // Ein Objekt das von "Obejct" erbt
// und 
var func1 = function(){}
// macht grundlegend das Gleiche wie
function func2() {}
// das erste ist eine "function expression" das zweite eine "function declaration".
// Beides erstellt ein Funktion. Sind aber in ein paar Details anders (z.B. wann sie vom Compiler erstellt werden).

Diese "Konstruktor Funktionen" ist JavaScript sind so ne Sache. Man hat die nur erfunden, damit JS nach Java aussieht. Die sind bei Prototypen basierter Verwebung aber nicht wirklich nötig und es verwirrt stark. Mal Schritt für Schritt:
Code:
var A = function(){
    this.foo = "hallo";
};
Was haben wir jetzt? A ist eine ganz normale Funktion, welche this.foo etwas zuweist.
"A.prototype" zeigt jetzt auf ein Objekt ohne Eigenschaften. Jede Funktion in JS bekommt übrigens die "prototype" Eigenschaft! Und hier liegt ein häufiges Missverständnis: Diese "prototype" Eigenschaft ist eine ganz normale Eigenschaft, welche standardmäßig auf ein leeres Objekt gesetzt wird. Die Eigenschaft hat noch nichts mit dem internen [[Prototype]] zu tun!! Jetzt macht man sowas:
Code:
var a = new A;
Was macht "new" jetzt? 3 Dinge:
1. Es erstellt ein neues Objekt, welches von A.prototype erbt. (Also etwa so: Object.create(A.prototype))
2. Jetzt wird die Konstruktor Funktion aufgerufen und das neu erstelle Objekt wird als Kontext (also als "this") an die Funktion übergeben
3. Das neue Objekt wird zurückgegeben

[[Prototype]] von a zeigt auf A.prototype. Das Objekt ist aber leer (erbt nur von "Obejct"). Sieht etwa so aus:
[a] -> [A.prototype Objekt] -> [Obejct] -> null

Man könnte dem prototype Objekt jetzt auch nachträglich Eigenschaften anfügen (wir haben ja eine Referenz zu dem internen [[Prototype]] über A.prototype:
Code:
a.foo; // => "hallo" (direkt auf dem a Objekt)
A.prototype.test = 42;
a.test; // => 42 (geerbt)
Aber Achtung:
Wir können [[Prototype]] von a nicht nachträglich austauschen!
Code:
A.prototype = {neu: 1234};
a.test // => 42 geht immer noch!
a.neu // gibt es nicht => undefined
Der [[Prototype]] von a ist intern eben fest gesetzt und das überschreiben von A.prototype ändert da nichts dran. Das ist eben nur eine normale Eigenschaft ;)
Wenn man jetzt aber A benutzt und ein neues Objekt macht, wird das neue Objekt als Prototyp verwendet:
Code:
a2 = new A;
a2.neu // => 1234
Etwa so: [a2] -> [neues Objekt] -> [Object] -> null

Damit solltest du deinen Code verstehen. Man muss eben verstehen was genau "new" macht und wie die "prototype" Eigenschaft von Funktionen in "new" genutzt wird (der Name verwirrt Anfänger schnell, denn das ist eben nicht der "richtige interne" Prototyp).

Und zu der "constructor" Eigenschaft:
Die macht garnichts besonderes. Ist einfach nur eine Referenz zu der Konstruktor Funktion. Die Eigenschaft sitzt übrigens automatisch in diesem "prototype" Objekt von Funktionen (ich hatte vorher gesagt es wäre leer, stimmt nicht so ganz ;))
Wenn man die "prototype" Eigenschaft von einer Funktion also mit einem eigenen Objekt überschreibt, kann man "constructor" selber wieder korrekt setzten. Ist aber nur eine Konvention, macht nichts mit der Funktionalität.

Ich hoffe es war halbwegs verständlich :D
Wenn du mehr wissen willst: Ich hab ein paar Dinge vereinfacht bzw. ausgelassen:
"instanceof" geht bei Object.create nicht. Mit "isPrototypeOf" und "getPrototypeOf" kann man auf [[Prototype]] zugreifen.
Mit "setPrototypeOf" kann man es sogar nachträglich ändern. Sollte man in der Praxis aber niemals machen (das ist nur ein Hack aus historischen Gründen).
 
Ok, das war schon mal deutlich besser erklärt! :) So langsam wächst mein Verständnis.

Hier noch einige Fragen anhand meines neuen Quelltextes:
Code:
function Halbgott(){
  this.haarfarbe = "blond";
};
Halbgott.prototype.beine = 2;

function Mann(name){
//  1. Frage
//  Mensch.call(this);
  this.name = name;
};
Mann.prototype.geschlecht = "maennlich";

Mann.prototype = new Halbgott;
// 2. Frage
//delete Halbgott.prototype.haarfarbe;

var mann = new Mann("Thor");



document.write( (mann instanceof Halbgott) + "<br>" );
document.write( (mann instanceof Mann) + "<br>" );
document.write( (mann.haarfarbe) + "<br>" );
document.write( (mann.beine) + "<br>" );
document.write( (mann.name) + "<br>" );

siehe Kommentar Zeile 7 (1. Frage)
Ich rufe im Konstruktor von "Mann" den Konstruktor von "Halbgott" nicht auf.
Trotzdem hat mein Objekt "mann", welches vom Typ "Mann" ist, die Eigenschaft der "haarfarbe" und die ist "blond".

Durch Vererbung kann dies ja nicht sein, weil die [[Prototype]] von Mann.prototype auf Halbgott.prototype verweist und Halbgott.prototype über keine Eigenschaft "haarfarbe" verfügt.

Wie kann das also sein!?


siehe Kommentar Zeile 14 (2. Frage)
In Tutorials wird oft empfohlen eine Eigenschaft von z.B. Halbgott, wie Halbgott.haarfarbe im [[Prototype]] von Halbgott, also Halbgott.prototype zu entfernen. Das verwirrt mich, da doch Halbgott.prototype diese Eigenschaft gar nicht hat, oder doch? Wenn doch, wie ist es dazu gekommen?
 
Ich vermute du stellst dir dieses "ableiten" noch im sinne von "extends" aus z.B. Java oder C++ vor. Das gibt es in JavaScript nur nicht, da man keine Klassen hat. Objekte erben immer von "Objekt Instanzen" direkt. (Wie in meinem Beispiel in Object.create, einfach nur Ketten)
"Konstruktor Funktionen" und "new" machen nix anderes. Ist eigentlich nur ein umständlicher Weg um so eine Kette aufzubauen.
Deshalb auch kein "super" oder das aufrufen von einem "Konstruktor" in einem anderen.
Ich schreib so viel in "", weil es dieses ganze Konzept von Klassen in JS nicht gibt ;)

Code:
Mann.prototype = new Halbgott;

Hier überschreibst du Mann.prototype mit einer "Instanz" von Halbgott. Also ein ganz normales Objekt. Wenn man jetzt "new Mann" macht, zeigt [[Prototype]] von so einer Mann "instanz" eben auf dieses Halbgott Objekt.
Dieses "Mann.prototype" zeigt "new" im Grunde nur, wovon geerbt werden soll (irgendwo her muss er es halt wissen :D). Und indem "new" dann noch automatisch "Halbgott()" aufruft, kann man halt noch Werte auf dem neuen Objekt setzten. Mehr passiert da wirklich nicht :)
Einfach nur Objekte und Funktion. Mehr gibt es in JS nicht^^

Code:
Mann.prototype.geschlecht = "maennlich";
Mann.prototype = new Halbgott;

Das macht nicht viel Sinn, denn du Überschreibst Mann.prototype ja komplett. Das Objekt auf dem "geschlecht" sitzt verlierst du also.
Mal als Beispiel (Objekte sind in JS immer nur Referenzen, etwa wie in Java):
Code:
var o = {};
o.foo = 123;
o = {bar: 321};
o.foo // ist undefined, das erste Objekt ist komplett überschrieben!
o.bar // => 321

Dein "var mann = new Mann("Thor")" macht etwa das:
Code:
mann --> {name: "Thor"}
         [[Prototype]] --> {haarfrabe: "blond"}
                           [[Prototype]] --> {beine: 2}
                                             [[Prototype]] --> {"die ganzen Eigenschaften von Object"}
                                                               [[Prototype]] --> null


Halbgott.prototype.haarfarbe zu löschen macht nicht viel sinn. Gibt es hier ja nicht und es würde doch eh von dem haarfrabe: "blond" verdeckt werden.
 
Ich habe das Konzept nun wohl vollständig gerafft. Leider gibt es nun massive Schwierigkeiten, aufgrund dieser schlechten Vererbungsrealisierung.

Beispiel:
Code:
function Mann(name, haarfarbe){
  Mann.prototype.name = name;
  Mann.prototype.haarfarbe = haarfarbe;
  Mann.prototype.geschlecht = "maennlich";
};

var mann_a = new Mann("Tom", "Bruenette");
var mann_b = new Mann("Hannes", "Blond");

document.write( (mann_a.haarfarbe)            + "<br>" );
document.write( (mann_a.name)                 + "<br>" );
document.write( (mann_a.geschlecht)           + "<br>" );

document.write( mann_a.prototype == mann_b.prototype   ); // true ...

Bei jedem Objekt (hier "mann_a" und "mann_b"), welches mit new und dem Mann-Konstruktor erstellt wird, zeigt die objekteigene {{prototyp}} auf Mann.prototype.
Jetzt verweist aber prinzipiell jede {{prototype}} des entsprechenden Objekts auf ein und die selbe Mann.prototype. Soll heißen, es gibt ja immer nur einen Prototypen ...

Wenn ich also "mann_b" erstelle, wird dessen Prototyp (Mann.prototype) mit den neuen Parametern überschrieben. Der Prototyp von "mann_b" ist aber der identisch selbe, wie der von "mann_a".

Das ist doch grässlich! :freak:

Ich kann auch nicht dafür sorgen, dass jedes Objekt einen exklusiven Prototypen zugewiesen bekommt.
 
Zuletzt bearbeitet von einem Moderator:
Hier ganz einfach im ES3 Standard von JS nach dem Pseudoklassischem Model.
Code:
// ES3 Vererbung
function Mensch(name, haarfarbe, geschlecht) {
    this.name = name;
    this.haarfarbe = haarfarbe;
    this.geschlecht = geschlecht;
    this.beine = 2;
}

// Prototypen außerhalb des Konstruktors festlegen, damit mehrere Instanzen auf die selbe Methode zeigen können (wird somit nur einmal im Speicher abgelegt)
Mensch.prototype.trinken = function () {
    return this.name + " trinkt etwas";
};

function Mann(name, haarfarbe, geschlecht, bart) {
    // Eigenschaften aus der Mensch Klasse werden mit aufgerufen
    Mensch.call(this, name, haarfarbe, geschlecht);
    this.bart = bart;
}

// Nur den Prototypen von Mensch hier angeben
// sonst werden die Eigenschaften im Konstruktor auch auf den Prototypen gelegt
// die dann ohne default value im Mensch Konstruktor undefined sind
Mann.prototype = Mensch.prototype;
Mann.prototype.constructor = Mann;

// Instanz
var bud = new Mann("Bud Spencer", "braun", "m", true);
bud.trinken();

Edit: Vllt. hilft das Video weiter https://www.youtube.com/watch?v=PMfcsYzj-9M
 
Zuletzt bearbeitet:
Evtl. beschäftigst du dich hierbei auch besser mit TypeScript. Ist n Präprozessor, kompiliert also in JS und bringt bereits einige Features von ECMAScript 6 mit.

Das Beispiel von palace4d mal in TypeScript:
Code:
class Mensch
{
	Name : string;
	Haarfarbe : string;
	Geschlecht : string;
	Beine : number;
	
	constructor( Name : string, Haarfarbe : string, Geschlecht : string )
	{
		this.Name = Name;
		this.Haarfarbe = Haarfarbe;
		this.Geschlecht = Geschlecht;
		this.Beine = 2;
	}
	
	trinken() : string
	{
		return this.Name + " trinkt etwas";
	}
}

class Mann extends Mensch
{
	Bart : boolean;
	
	constructor( Name : string, Haarfarbe : string, Geschlecht : string, Bart : boolean )
	{
		super( Name, Haarfarbe, Geschlecht );
		this.Bart = Bart;
	}
}

var bud = new Mann( "Bud Spencer", "braun", "m", true );
bud.trinken();
Und kompiliert in JS:
Code:
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var Mensch = (function () {
    function Mensch(Name, Haarfarbe, Geschlecht) {
        this.Name = Name;
        this.Haarfarbe = Haarfarbe;
        this.Geschlecht = Geschlecht;
        this.Beine = 2;
    }
    Mensch.prototype.trinken = function () {
        return this.Name + " trinkt etwas";
    };
    return Mensch;
})();
var Mann = (function (_super) {
    __extends(Mann, _super);
    function Mann(Name, Haarfarbe, Geschlecht, Bart) {
        _super.call(this, Name, Haarfarbe, Geschlecht);
        this.Bart = Bart;
    }
    return Mann;
})(Mensch);
var bud = new Mann("Bud Spencer", "braun", "m", true);
bud.trinken();
 
Tersus schrieb:
Jetzt verweist aber prinzipiell jede {{prototype}} des entsprechenden Objekts auf ein und die selbe Mann.prototype. Soll heißen, es gibt ja immer nur einen Prototypen ...

Jup, deswegen macht man ja überhaupt Vererbung. Viele Objekte erben von einem. Bringt Performance und spart viel Speicher, denn es muss nicht jede Instanz die ganzen Eigenschaften und Methoden kopieren.
Wenn ein Objekt eigene Eigenschaften haben soll, einfach direkt auf das Objekt setzen (die können sich ja z.B. auch "verdecken"). palace4d hat ja nen schönes Beispiel gezeigt.
Man darf nicht zu komplex denken :D
Ein Objekt kann eben der Prototyp für viele andere sein. Das ist im Grunde alles. Mehrfachvererbung oder so gibt es in JS nicht.

In dem neusten JavaScript Standard (ES6) gibt es übrigens auch "Klassen". Genau so wie in TypeScript ist das allerdings nur extra Syntax.
Die Vererbung dahinter ist immernoch Prototypen basiert.
 
Danke euch allen für die Unterstützung!

Eine Sache ist immernoch nicht ganz kapiert ... :freak:, daher habe ich auch ein kleines Problem, das Beispiel von palace4d zu verstehen.

Code:
function Mensch(){
  this.name = "eric";
};

function Mann(){
  this.geschlecht = "maennlich";
};

Mann.prototype = Mensch.prototype;
// Mann.prototype.constructor = Mann;

var mann = new Mann();

document.write( (mann.name)       + "<br>" );
document.write( (mann.geschlecht) + "<br>" );
document.write( (mann.prototype == Mensch.prototype) + "<br>" ); // false

Zeile 9: Was passiert genau?
Meine Interpretation: Mann.prototype ist nun Mensch.prototype. Mensch.prototype.constructor zeigt entsprechend auf Mensch, also muss auch Mann.prototype.constructor auf Mensch zeigen.

Die {{prototype}} meines mann Objekts zeigt auf Mann.prototype, welche ja durch Zeile 9 eigentlich zu Mensch.prototype wurde, oder!?
Laut dem Vergleichstest in Zeile 16 stimmt das aber nicht.
 
Zuletzt bearbeitet von einem Moderator:
Hmm, fällt mir auch jetzt erst auf. Ist ne recht ungewöhnliche Technik. Da wird eigentlich nur die "Mensch" Funktion zum setzten der Eigenschaften genutzt. Wirklich geerbt ist das auch nicht.
Normalerweise nimmt man als Prototyp eine Instanz der Oberklasse. Aber es gibt einige Tricks um ein "extends" zu faken. Dieses aufgesetzte Klassensystem kommt halt schnell an seine Grenzen, wenn man sowas wie Java nachmachen will. Da erbt man ja von eine "Klasse" und nicht von einer Instanz direkt.
Man sollte in JavaScript auch nicht alles mit diesen Konstruktoren bewerfen. Häufig kommt man auch gut ohne aus, man kann Objekte ja eh beliebig zur Laufzeit aufbauen und Funktionen sind auch sehr flexibel.
Ich würde empfehlen sich einfach in bekannten Bibliotheken und Frameworks umzusehen und zu gucken was für Design Patterns die verwenden.
Und ich würde auch console.log(objekt) zum testen empfehlen. In den Browser-Konsolen kann man die Objekte dann schön inspizieren und das hilft stark beim verstehen von Strukturen.
In Webbrowser haben alle Objekten übrigens eine Eigenschaft namens "__proto__". Die zeigt genau auf diesen [[Prototyp]] von Objekten. Das kann man sich in der Konsole schön angucken.
(diese komische Eigenschaft gehört übrigens nicht zum JavaScript-Standard, also Vorsicht :D)
 
Zuletzt bearbeitet:
Zeile 9: Was passiert genau?
Meine Interpretation: Mann.prototype ist nun Mensch.prototype. Mensch.prototype.constructor zeigt entsprechend auf Mensch, also muss auch Mann.prototype.constructor auf Mensch zeigen.
Funktionen sind in JS auch Objekte (genauer gesagt first-class). Gib mal in der Browserconsole folgendes ein console.dir(var a = function myFnA (){}). Dort findest du verschiedene Eigenschaften wie arguments, caller, length, name, prototype und __proto__. Jetzt kannst du bspw. per a.name auf die name Eigenschaft der Funktion zugreifen, als Rückgabewert solltest du den String myFnA erhalten.

Wie schon erwähnt ist ein Prototyp ein Objekt. Jede Funktion, die erzeugt wird, erhält automatisch dieses prototype Objekt. Es zeigt auf ein neues leeres Objekt. Der Inhalt dieses Objektes ist fast identisch mit einem Objekt, das per Objektliteral oder über den Objektkonstruktor erzeugt wurde.
Der Unterschied leigt in der Eigenschaft constructor , welche auf die erzeugende Funktion verweist und nicht auf das eingebaute Object. Dem leeren Objekt der Funktion können Eigenschaften/Methoden hinzugefügt werden. Andere Objekte können diese auch erben, so dass diese die können Eigenschaften/Methoden auch verwenden können.

Normalerweise nimmt man als Prototyp eine Instanz der Oberklasse
Das hat aber zwei Nachteile
1. Der Prototyp wird mit dem Inhalt der Instanz "verunreinigt"
2. Es wird die Instanz aufgerufen, obwohl im eigtl. Sinne keine Instanz erzeugt wird

http://jsbin.com/nudikivehi/1/edit

Hier einfach mal die Logs vergleichen wenn man die Zeile ändert.
Code:
Mann.prototype = Mensch.prototype;
//Mann.prototype = new Mensch;

Oder ES5: Mann.prototype = Object.create(Mensch.prototype)
 
Zuletzt bearbeitet:
Ich greife noch mal den Quelltext von oben auf.

Code:
Mann.prototype = Mensch.prototype;
Mann.prototype.constructor = Mann;

Zeile 1: Das Prototyp-Objekt von Mann ist nun das identische Prototyp-Objekt von Mensch.
Zeile 2: Der Konstruktor, welcher sich immer in dem Prototyp einer Funktion befindet, zeigt dadurch auf Mensch und muss auf Mann abgeändert werden, damit unsere neuen Objekte, die den Mann Konstruktor verwenden, auch als Instanzen von Mann erkannt werden.
Nun wieder die Vererbungsproblematik: Nun verweist die interne {{prototype}} eines jeden neuen Objekts, welches mit new und dem Mensch-Konstruktor (nicht Mann) erstellt wird, auf Mensch.prototype. Mensch.prototype ist aber durch Zeile 2 identisch zu Mann.prototype und da haben wir den Konstruktor auf Mann gesetzt. Soll heißen unsere Mensch-Objekte sind nun auch wieder Instanzen von Mann. :rolleyes:

Code:
var mensch = new Mensch();
document.write( mensch instanceof Mann ) // true;

Was für ein Dilemma. Ich habe es aber gerafft. :evillol:
Danke für die vielen hilfreichen Beiträge.

Grüße
 
Zurück
Oben