La prima differenza può essere riassunta come: si this
riferisce all'istanza della classe. prototype
si riferisce alla definizione .
Diciamo che abbiamo la seguente classe:
var Flight = function ( number ) { this.number = number; };
Quindi qui ci stiamo collegando this.number
a ogni istanza della classe, e ha senso perché ognuno Flight
dovrebbe 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 otterranno 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 Object principale (l'oggetto da cui tutto il resto ha ereditato) e non appena trova una corrispondenza restituisce o lo chiama.
Ma ciò accade solo per le proprietà prototipate. Quindi, se hai un posto nei livelli più alti this.whatever
, JavaScript non lo considererà una corrispondenza e continuerà la ricerca.
Vediamo come succede nella realtà.
Per prima cosa, [quasi] tutto è Oggetti in JavaScript. Prova questo:
typeof null
Ora vediamo cosa c'è dentro un Object
(notare il maiuscolo O
e .
alla fine). In Strumenti per gli sviluppatori di Google Chrome quando si immette il .
comando, verrà visualizzato un elenco di proprietà disponibili all'interno di quell'oggetto specifico.
Object.
Ora fai la stessa cosa per Function
:
Function.
Potresti notare il name
metodo. Basta andare a accenderlo e vediamo cosa succede:
Object.name
Function.name
Ora creiamo una funzione:
var myFunc = function () {};
E vediamo se abbiamo anche il name
metodo qui:
myFunc.name
Dovresti ottenere una stringa vuota, ma va bene. Non dovresti ricevere un errore o un'eccezione.
Ora aggiungiamo qualcosa a quel dio Object
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 "Okay!"
.
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. this
è piuttosto più complicato poiché rilevante per il contesto. Puoi trovare molte buone risorse gratuitamente su Internet.
Detto questo, entrambi i modi sono solo strumenti linguistici e dipende davvero da te e dal problema che stai cercando di risolvere per scegliere ciò che si adatta meglio.
Se è necessario disporre di una proprietà che sia pertinente per ogni istanza di una classe, utilizzare this
. Se è necessario disporre di una proprietà per funzionare allo stesso modo in ogni istanza, utilizzare prototype
.
Aggiornare
Per quanto riguarda i frammenti di esempio, il primo è un esempio di Singleton , quindi ha senso utilizzarlo this
nel corpo dell'oggetto. Puoi anche migliorare il tuo esempio rendendolo modulare in questo modo (e non è necessario utilizzarlo 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 frammento non ha molto senso perché prima stai usando this
e poi stai cercando di hackerarlo prototype
, il che non funziona perché this
ha la priorità prototype
. Non sono sicuro di quali fossero le tue aspettative da quel pezzo di codice e come funzionasse, ma ti consiglio vivamente di rifattorizzarlo.
Aggiornare
Per elaborare la this
precedenza, prototype
posso mostrarti un esempio e dirti come può essere spiegato, ma non ho alcuna risorsa esterna per 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, this
rilevante per il contesto. Quindi non verrà all'esistenza fino a quando il contesto non sarà pronto. Quando il contesto è pronto? Quando viene creata la nuova istanza! Dovresti indovinare il resto adesso! Significa che anche se esiste una prototype
definizione, ma this
ha più senso avere la precedenza perché si tratta della nuova istanza creata in quel momento.