2012-07-26 10 views
11

Sto progettando una gerarchia di classi in JavaScript. Funziona bene finora, ma non riesco a vedere come determinare se un oggetto è una "istanza" di una classe genitore. Esempio:javascript oop, instanceof e classe base

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(); tronchi questo:

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

mentre second.sayWhoAmI(); registra questo:

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

mi sento come sia oggetto first e second dovrebbe avere dire che sono istanze di BaseObject.

Comprendo che JavaScript non può essere creato per questo, ma mi chiedo se c'è un modo per farlo.

+6

chiamando Solo 'Base.apply (...)' non lo fa l'installazione eredità. Devi impostare correttamente il prototipo. Vedi: http://jsfiddle.net/fkling/wJE6s/. Dai anche un'occhiata a questa domanda per una spiegazione: http: // StackOverflow.it/questions/3145700/javascript-inheritance-instanceof-not-working? rq = 1 –

+1

Felix dovresti scrivere questo come risposta, questo è esattamente ciò di cui ho bisogno e il tuo violino lo dimostra semplicemente. Non permettere a qualcun altro di rubare la tua reputazione! – Johnny5

+0

Concordato che dovrebbe aggiungere una risposta, ma probabilmente non è preoccupato di aumentare il suo rappresentante dello 0,01%! – jahroy

risposta

10

Solo chiamando Base.apply(...) non imposta l'ereditarietà. Tutto ciò che .apply fa è impostare this sul primo argomento, nient'altro. È importante chiamare il costruttore genitore, ma non è sufficiente.

Quello che devi fare è impostare correttamente la catena del prototipo. Cioè, devi impostare Derivation1.prototype su qualcosa che eredita da Base.prototype.

Dal momento che ogni istanza di una funzione di costruzione eredita dal prototipo di The funzioni di costruzione, si vedrà codice come

Derivation1.prototype = new Base(); 

Questo è una cattiva idea e si può già vedere perché: Base aspetta argomenti per impostare su proprietà specifiche dell'istanza (name in questo caso). Ma non ci interessano queste proprietà, dal momento che le iniziamo in seguito nel costruttore bambino con Base.apply(this, ...).

Quindi tutti abbiamo bisogno è un oggetto che eredita dalla Base.prototype e per fortuna, ECMAScript 5 definisce una funzione che può farlo per noi (polyfill):

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

Questo crea un nuovo oggetto che eredita dalla Base.prototype. Ora, dal momento che è stato sostituito il prototipo originale con un nuovo oggetto, è necessario impostare la proprietà constructor in modo che punti correttamente per Derivation1:

Derivation1.prototype.constructor = Derivation1; 

Di seguito è riportato un esempio completo. Date anche un'occhiata a this fiddle e this excellent answer by T.J. Crowder, che spiega fondamentalmente gli stessi problemi, ma forse in un modo migliore.


Esempio:

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(); 

Problemi correlati