5

Powiedzmy mam obiekt gracza:JS Prototypal Inheritance: childs używają tych samych właściwości rodzica?

var player = function(name) { 
    this.handlers = {}; 
} 

player.prototype.on = function(event, callback) { 
    if (!this.handlers[event]) { 
     this.handlers[event] = []; 
    } 
    this.handlers[event].push(callback); 
} 

Działa świetnie, mogę tworzyć graczy i każdy będzie miał swój własny zestaw ładowarki. Załóżmy teraz, że muszę dziedziczą player:

var testPlayer = function(name) { 
    this.name = name; 
}; 

testPlayer.prototype = new player(); 

teraz, gdy tworzę testPlayer „s, a każdy z nich podziela tą handlers właściwość:

var adam = new testPlayer('Adam'); 
adam.on('test', function(){}); 

var eve = new testPlayer('Eve'); 
// eve.handlers == {'test':<function>} 

Co ja tu brakuje? Rozumiem, że każdy prototyp testPlayer jest tym samym obiektem, który utworzę podczas opisu klasy potomnej. Ale czy istnieje jakiś sposób, aby wszystkie testPlayery miały swój własny zestaw procedur?

Odpowiedz

5

To z pewnością wygląda dziwnie dla tych, które są używane do dziedziczenia klasycznego, ale tak działa prototypowe dziedziczenie. Aby mieć osobny obiekt obsługi na wystąpienie, należy określić go w konstruktorze podrzędnym. To będzie śledzony obiekt prototypu jest o tej samej nazwie:

var testPlayer = function(name) { 
    this.name = name; 
    this.handlers = {}; 
}; 

testPlayer.prototype = new player(); 

Innym rozwiązaniem byłoby stworzenie tej shadowing nieruchomości na żądanie, z metody on:

player.prototype.on = function(event, callback) { 
    // Check for a handlers property on the instance 
    if(!this.hasOwnProperty('handlers') { 
     this.handlers = {}; 
    } 
    if (!this.handlers[event]) { 
     this.handlers[event] = []; 
    } 
    this.handlers[event].push(callback); 
} 

Ciekawostka

Jest to problem tylko wtedy, gdy modyfikuje się właściwości obiektu (lub tablicy) na prototypie. Jeśli spróbujesz przypisać do właściwości, które znajdują się na prototypie, lokalna właściwość shadowowania zostanie utworzona automatycznie (nie można przypisać do właściwości prototypu z instancji).

+1

+1 do "innego rozwiązania", to wygląda jak najbardziej użyteczny. –

+0

Zgadzam się, to całkowicie poprawny paradygmat programowania. Denerwujące jest to, że musisz dodać taką kontrolę w każdej metodzie, która używa 'obsługi". – MaxArt

+0

Możesz mieć pojedynczą metodę 'init' wywołaną z konstruktora i zrobić to z tego miejsca. Zauważ, że jest to problem tylko wtedy, gdy modyfikujesz właściwości obiektu (lub tablicy) na prototypie. Jeśli spróbujesz przypisać do właściwości, które znajdują się na prototypie, lokalna właściwość shadowowania zostanie utworzona automatycznie (nie można przypisać do właściwości prototypu z instancji). – bfavaretto

1

Problem polega na tym, że handlers to właściwość, która została dodana w konstruktorze, więc kiedy robisz

testPlayer.prototype = new player(); 

dodajesz każdą własność nowym player obiektu testPlayer.prototype, i że zawierahandlers.

Tak, tam jest nieruchomość w każdym testPlayer obiektu handlers, a kiedy dodać obiekt do handlers dodajesz własności do obiektu w prototypie i nie stanowi przedmiotu testPlayer.

W skrócie, gdy wywołanie metody on dodajesz obiekt do testPlayer.prototype.handlers, nie adam.handlers lub eve.handlers.

Aby być bezpiecznym, należy zdefiniować:

var testPlayer = function(name) { 
    this.name = name; 
    this.handlers = {}; 
}; 
Powiązane problemy