2012-07-26 13 views
11

Projektuję niektóre klasy hierarchii w JavaScript. Do tej pory działa dobrze, ale nie wiem, jak określić, czy obiekt jest "instancją" klasy nadrzędnej. Przykład:javascript oop, instanceof i klasa podstawowa

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(); kłody następująco:

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

podczas gdy second.sayWhoAmI(); kłody następująco:

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

czuję się zarówno first i second obiekt powinien mieć powiedzieć, że są przypadki BaseObject.

Rozumiem, że JavaScript może nie być do tego stworzony, ale zastanawiam się, czy istnieje sposób, aby to osiągnąć.

+6

Tylko wywołanie 'Base.apply (...)' nie instalacyjny dziedziczenia. Musisz poprawnie ustawić prototyp. Zobacz: http://jsfiddle.net/fkling/wJE6s/. Popatrz na to pytanie, aby uzyskać wyjaśnienie: http: // stackoverflow.com/questions/3145700/javascript-inheritance-instanceof-not-working? rq = 1 –

+1

Felix, powinieneś napisać to jako odpowiedź, dokładnie tego potrzebuję, a twoje skrzypce po prostu to pokażą. Nie pozwól, by ktoś inny ukradł twoją reputację! – Johnny5

+0

Uzgodniono, że powinien dodać odpowiedź, ale prawdopodobnie nie martwi się o zwiększenie swojego powtórzenia o 0,01%! – jahroy

Odpowiedz

10

Tylko wywołanie Base.apply(...) nie powoduje ustawienia dziedziczenia. Wszystko to powoduje, że this ustawia się na pierwszy argument, nic więcej. Ważne jest wywołanie konstruktora macierzystego, ale nie jest to wystarczające.

Co musisz zrobić, to poprawnie ustawić łańcuch prototypów. Oznacza to, że musisz ustawić Derivation1.prototype na coś, co dziedziczy po Base.prototype.

Ponieważ każda instancja funkcji konstruktora dziedziczy od prototypu funkcji konstruktora, widać kod, takich jak

Derivation1.prototype = new Base(); 

To zły pomysł i już można zobaczyć, dlaczego: Base spodziewa się argumenty, aby ustawić do właściwości specyficznych dla instancji (name w tym przypadku). Ale nie dbamy o te właściwości, ponieważ inicjujemy je później w konstruktorze podrzędnym z Base.apply(this, ...).

Więc musimy to obiekt dziedziczy z Base.prototype i szczęśliwie, ECMAScript 5 definiuje funkcję, która może to zrobić za nas (polyfill):

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

ta tworzy nowy obiekt dziedziczy z Base.prototype. Teraz, od kiedy zastąpił oryginalny prototyp z nowym obiektem, trzeba ustawić właściwość constructor tak aby wskazywał poprawnie Derivation1:

Derivation1.prototype.constructor = Derivation1; 

Poniżej znajduje się pełna przykładów. Zobacz także this fiddle i this excellent answer by T.J. Crowder, które wyjaśniają zasadniczo te same problemy, ale może w lepszy sposób.


Przykład:

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

Powiązane problemy