5

Diciamo che ho oggetto Player:JS Prototypal Inheritance: i child utilizzano le stesse proprietà genitore?

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

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

Funziona benissimo, posso creare giocatori e ognuno avrà il proprio insieme di gestori. Ora supponiamo ho bisogno di ereditare da player:

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

testPlayer.prototype = new player(); 

Ora, quando creo testPlayer 's, ognuno dei quali condividono la stessa handlers proprietà:

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

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

Che cosa mi manca qui? Capisco che ogni prototipo dello testPlayer è lo stesso oggetto new player che creo quando descrivo la classe figlio. Ma c'è un modo per tutti i giocatori di prova di avere il proprio set di gestori?

risposta

5

Questo sicuramente sembra strano per quelli usati per l'ereditarietà classica, ma è come funziona l'eredità prototipale. Per avere un oggetto gestori separati per istanza, è necessario specificarne uno sul costruttore figlio. Che ombra proprietà del prototipo con lo stesso nome:

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

testPlayer.prototype = new player(); 

Un'altra soluzione potrebbe essere quella di creare questa struttura shadowing on-demand, dal on metodo:

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

Fatto interessante

Questo è solo un problema se si modificano le proprietà di un oggetto (o matrice) sul prototipo. Se si tenta di assegnare alle proprietà che vivono sul prototipo, verrà creata automaticamente una proprietà di shadowing locale (non è possibile assegnare le proprietà di prototipo alle istanze).

+1

+1 per la "un'altra soluzione", questo sembra il più utilizzabile. –

+0

Sono d'accordo, questo è un paradigma di programmazione totalmente valido. La parte fastidiosa è che devi aggiungere un controllo di questo tipo in ogni metodo che usa i 'gestori'. – MaxArt

+0

Si potrebbe avere un singolo metodo 'init' chiamato dal costruttore e farlo da lì. Si noti che questo è solo un problema se si modificano le proprietà di un oggetto (o array) sul prototipo. Se si tenta di assegnare alle proprietà che vivono sul prototipo, verrà creata automaticamente una proprietà di shadowing locale (non è possibile assegnare le proprietà di prototipo alle istanze). – bfavaretto

1

Il problema qui è che handlers è una struttura che è stata aggiunta nel costruttore, in modo che quando si fa

testPlayer.prototype = new player(); 

si aggiunge ogni proprietà di un nuovo oggetto da playertestPlayer.prototype, e che includehandlers.

Quindi, c'è una proprietà handlers in ogni oggetto testPlayer, e quando si aggiunge una proprietà da handlers si sta aggiungendo la proprietà all'oggetto nel prototipo, e non dell'oggetto testPlayer.

In breve, quando si chiama il metodo on si sta aggiungendo una proprietà da testPlayer.prototype.handlers, non adam.handlers o eve.handlers.

di essere al sicuro, definire:

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