La prima differenza può essere riassunta come: this
si riferisce all'istanza della classe. prototype
si riferisce a Definizione .
Diciamo che abbiamo la seguente classe:
var Flight = function ( number ) { this.number = number; };
Quindi, qui stiamo associando this.number
a ogni istanza della classe e ha senso perché ogni Flight
deve avere il proprio numero di volo.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Al contrario, prototype
definisce una singola proprietà a cui è possibile accedere da tutte le istanze.
Ora, se vogliamo ottenere il numero di volo, possiamo semplicemente scrivere il seguente frammento e tutte le nostre istanze avranno un riferimento a questo oggetto appena prototipato.
Flight.prototype.getNumber = function () { return this.number; };
La seconda differenza riguarda il modo in cui JavaScript cerca una proprietà di un oggetto. Quando stai cercando Object.whatever
, JavaScript arriva fino all'oggetto Oggetto principale (l'oggetto da cui tutto il resto ha ereditato) e non appena trova una corrispondenza verrà restituito o chiamalo.
Ma ciò accade solo per le proprietà prototipate. Pertanto, se hai un livello superiore dithis.whatever
in più, JavaScript non lo considererà una corrispondenza e continuerà la ricerca.
Vediamo come succede nella realtà.
Prima nota che [quasi] tutto è Oggetti in JavaScript. Prova questo:
typeof null
Ora vediamo cosa c'è dentro un Object
(annota il% maiuscolo% co_de e il O
alla fine). Negli Strumenti per sviluppatori di Google Chrome quando inserisci .
otterrai un elenco di proprietà disponibili all'interno dell'oggetto specifico.
Object.
Ora fai la stessa cosa per .
:
Function.
Potresti notare il metodo Function
. Basta andare, accenderlo e vediamo cosa succede:
Object.name
Function.name
Ora creiamo una funzione:
var myFunc = function () {};
E vediamo anche qui il metodo name
:
myFunc.name
Dovresti ottenere una stringa vuota, ma va bene. Non dovresti ricevere un errore o un'eccezione.
Ora aggiungiamo qualcosa a quel dio-come name
e vediamo se lo otteniamo anche in altri posti?
Object.prototype.test = "Okay!";
Ed ecco qua:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
In tutti i casi dovresti vedere Object
.
Per quanto riguarda i pro e i contro di ogni metodo, puoi considerare la prototipazione come un modo "più efficiente" di fare le cose, poiché mantiene un riferimento su ogni istanza piuttosto che copiare l'intera proprietà in ogni oggetto. D'altra parte è un esempio di Accoppiamento stretto che è un grande no-no fino a quando non si può davvero giustificare il motivo. "Okay!"
è molto più complicato dal momento che è rilevante per il contesto. Puoi trovare molte buone risorse gratuitamente in Internet.
Ciò detto, entrambi i modi sono solo strumenti linguistici e dipendono davvero da te e dal problema che stai cercando di risolvere per scegliere ciò che si adatta meglio.
Se è necessario che una proprietà sia pertinente per ogni istanza di una classe, utilizzare this
. Se è necessario disporre di una proprietà per funzionare allo stesso modo su ogni istanza, utilizzare this
.
Aggiorna
Per quanto riguarda i frammenti di esempio, il primo è un esempio di Singleton , quindi ha senso utilizzare prototype
nel corpo dell'oggetto. Puoi anche migliorare il tuo esempio rendendolo modulare come questo (e non devi usare sempre this
).
/* Assuming it will run in a web browser */
(function (window) {
window.myApp = {
...
}
})( window );
/* And in other pages ... */
(function (myApp) {
myApp.Module = {
...
}
})( myApp );
/* And if you prefer Encapsulation */
(function (myApp) {
myApp.Module = {
"foo": "Foo",
"bar": function ( string ) {
return string;
},
return {
"foor": foo,
"bar": bar
}
}
})( myApp );
Il tuo secondo snippet non ha molto senso perché in primo luogo stai utilizzando this
e in seguito stai tentando di modificarlo con this
, che non funziona perché prototype
ha la priorità su this
. Non sono sicuro di quali fossero le tue aspettative da quel pezzo di codice e di come funzionava, ma ti raccomando caldamente di refactoring.
Aggiorna
Elaborare su prototype
prendendo la precedenza su this
Posso mostrarti un esempio e dirti come può essere spiegato, ma non ho alcuna risorsa esterna per eseguirne il backup.
L'esempio è molto semplice:
var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";
var obj = new myClass;
obj.foo; // Still contains "Foo" ...
obj.bar; // Contains "Bar" as expected
La spiegazione è, come sappiamo, prototype
è rilevante per il contesto. Quindi non verrà all'esistenza finché il contesto non sarà pronto. Quando il contesto è pronto? Quando viene creata la nuova istanza! Dovresti indovinare il resto ora! Significa che anche se esiste una definizione this
, ma prototype
ha più senso per avere la precedenza perché è tutto incentrato sulla nuova istanza creata in quel momento.