2012-07-26 1 views
11

Ich entwerfe einige Klassenhierarchie in JavaScript. Es funktioniert soweit gut, aber ich kann nicht sehen, wie zu bestimmen, ob ein Objekt eine "Instanz" einer Elternklasse ist. Beispiel:Javascript oop, instanceof und Basisklasse

function BaseObject(name){ 
    this.name = name; 

    this.sayWhoAmI = function(){ 
     console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1)); 
     console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2)); 
     console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject)); 
    }; 
} 
function Derivation1(){ 
    BaseObject.apply(this, ['first derivation']); 
} 
function Derivation2(){ 
    BaseObject.apply(this, ['second derivation']); 
} 

var first = new Derivation1(); 
var second = new Derivation2(); 

first.sayWhoAmI(); protokolliert diese:

first derivation is a Derivation1 : true 
first derivation is a Derivation2 : false 
first derivation is a BaseObject : false 

während second.sayWhoAmI(); protokolliert diese:

second derivation is a Derivation1 : false 
second derivation is a Derivation2 : true 
second derivation is a BaseObject : false 

Ich fühle mich wie sowohl first und second Objekt sollte sagen, dass sie Instanzen von BaseObject sind.

Ich verstehe, dass JavaScript möglicherweise nicht dafür gemacht wird, aber ich frage mich, ob es einen Weg gibt, das zu erreichen.

+6

Nur Aufruf 'Base.apply (...)' nicht Vererbung Setup. Sie müssen den Prototyp richtig einstellen. Siehe: http://jsfiddle.net/fkling/wJE6s/. Werfen Sie einen Blick auf diese Frage, um eine Erklärung zu erhalten: http: // stackoverflow.com/questions/3145700/javascript-vererbung-instanceof-nicht-arbeiten? rq = 1 –

+1

Felix sollten Sie dies als Antwort schreiben, das ist genau das, was ich brauche und Ihre Geige demonstrieren es einfach. Lass niemanden deinen Ruf stehlen! – Johnny5

+0

Einverstanden, er sollte eine Antwort hinzufügen, aber er macht sich wahrscheinlich keine Sorgen darüber, seinen Ruf um 0,01% zu steigern! – jahroy

Antwort

10

Nur beim Aufruf von Base.apply(...) wird keine Vererbung eingerichtet. All das .apply macht this auf das erste Argument, nichts anderes. Es ist wichtig, den übergeordneten Konstruktor aufzurufen, aber das ist nicht ausreichend.

Was Sie tun müssen, ist die Prototypkette richtig aufzustellen. Das heißt, Sie müssen Derivation1.prototype auf etwas setzen, das von Base.prototype erbt.

Da jede Instanz einer Konstruktor-Funktion vom Konstruktorfunktionen Prototyp erbt, werden Sie Code sehen wie

Derivation1.prototype = new Base(); 

Dies ist eine schlechte Idee und man kann schon sehen, warum: Base Argumente erwartet einstellen up Instanz spezifischen Eigenschaften (name in diesem Fall). Aber diese Eigenschaften interessieren uns nicht, da wir sie später im Kindkonstruktor mit Base.apply(this, ...) initialisieren.

Also alles, was wir brauchen, ist ein Objekt aus Base.prototype vererben und zum Glück, ECMAScript 5 definiert eine Funktion, die das für uns tun kann (polyfill):

Derivation1.prototype = Object.create(Base.prototype); 

Dies ein neues Objekt erstellt von Base.prototype vererben. Nun, da Sie den Original-Prototyp mit einem neuen Objekt ersetzt, haben Sie die constructor Eigenschaft zu setzen, so dass es richtig Derivation1 Punkte:

Derivation1.prototype.constructor = Derivation1; 

Im Folgenden ein vollständiges Beispiel ist. Werfen Sie auch einen Blick auf this fiddle und this excellent answer by T.J. Crowder, die im Grunde die gleichen Probleme, aber vielleicht auf eine bessere Weise erklärt.


Beispiel:

function BaseObject(name){ 
    this.name = name; 
} 

// move properties shared by all instances to the prototype! 
BaseObject.prototype.sayWhoAmI = function() { 
    console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1)); 
    console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2)); 
    console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject)); 
}; 

function Derivation1(){ 
    BaseObject.apply(this, ['first derivation']); 
} 

Derivation1.prototype = Object.create(BaseObject.prototype); 
Derivation1.prototype.constructor = Derivation1; 

// some useless method of the child "class" 
Derivation1.prototype.someOtherMethod = function() { 
    return 42; 
}; 

var first = new Derivation1(); 
first.sayWhoAmI();