2016-05-06 32 views
6

cerco di ignorare un metodo e script è:Javascript non chiama il metodo prototipo

function wrapper(target) { 
    target.doABC = function() { 
     alert('in wrapper'); 
    }; 
    return target; 
} 

function Model() { 
    wrapper(this); 
} 

Model.prototype.doABC = function() { 
    alert('in Model'); 
}; 

var a = new Model(); 
a.doABC(); 

Il risultato è 'in wrapper'. Non so perché?

+0

'Modello' è un' oggetto' e un 'oggetto' non può avere 2 chiavi con lo stesso nome! – Rayon

+0

@Rayon: 'shadow', non' override', per usare una terminologia migliore. L'OP non sta assegnando una proprietà a 'Model' due volte, sta assegnando a' Model' e al prototipo. –

+0

@JeremyJStarcher, True. Il termine "override" interpreterà male le cose .. – Rayon

risposta

5

Qualsiasi oggetto JavaScript ha proprio e proprietà ereditate. Proprio sono quelli definiti direttamente nell'istanza e ereditato sono presi dall'oggetto prototype.
Quando si utilizza un accessorio di proprietà , le prime ricerche di JavaScript nell'elenco proprietà dell'oggetto. Se la proprietà non viene trovata, cerca nella catena di prototipi dell'oggetto.

Nell'esempio, il metodo wrapper() definisce sull'istanza dell'oggetto una proprietà doABC, che è una funzione che avvisa 'in wrapper'. Anche se l'oggetto ha un prototipo con la stessa proprietà doAbc che avvisa 'in Model', JavaScript utilizzerà comunque la proprietà.

function wrapper(target) { 
    // Define an own property "doABC" 
    target.doABC = function() { 
     alert('in wrapper'); 
    }; 
    return target; 
} 

function Model() { 
    wrapper(this); 
} 

// Define an inherited property "doABC" 
Model.prototype.doABC = function() { 
    alert('in Model'); 
}; 

var a = new Model(); 

//Use the own property "doABC". The inherited "doABC" is ignored. 
a.doABC(); 

In aggiunta, la proprietà può essere rimosso utilizzando delete operatore. Dopo l'eliminazione, l'oggetto utilizzerà la proprietà ereditata.

// delete the own property "doABC" 
delete a['doABC']; 

// the inherited "doABC" will be used. Alerts "in Model" 
a.doABC(); 

Verificare l'intero working demo.

+0

Grazie per la risposta! – user3468795

+0

Ho provato a eseguire il debug di questo script. Prima di eseguire l'istruzione target.doABC, l'oggetto a ha già il metodo doABC() che proviene dal prototipo.Dopo aver eseguito target.doABC, questa funzione viene aggiornata. – user3468795

+0

@ user3468795 Sì, succede in questo modo nel costruttore. La mia risposta è per la domanda 'Il risultato è 'in wrapper'. Non so perché? '. –

1

Fammi vedere se riesco a spiegarmi:

Hai due versioni separate di doABC qui.

tuo target.doABC crea una funzione specifica per che istanza del Model e ogni Model ottenere la propria doABC.

Perché Model dispone di un doABC, il motore JavaScript non ha bisogno di cercare "la catena" per qualcos'altro, quindi non cercherà mai la versione Model.prototype.doABC.

È possibile vedere questo con l'aggiunta di queste righe:

Model.prototype.doXYZ = function() { 
    alert('in Model'); 
}; 

e chiamando

a.doXYZ(); 

Dal a non ha una propria doXYZ allora, e solo allora, si guarda in alto nella catena e vedi il metodo nel prototipo.