La prima differenza può essere riassunta come: si thisriferisce all'istanza della classe. prototypesi riferisce alla definizione .
Diciamo che abbiamo la seguente classe:
var Flight = function ( number ) { this.number = number; };
Quindi qui ci stiamo collegando this.numbera ogni istanza della classe, e ha senso perché ognuno Flightdovrebbe avere il proprio numero di volo.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Al contrario, prototypedefinisce 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 Oe .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 namemetodo. 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 namemetodo 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 Objecte 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 thisnel 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 thise poi stai cercando di hackerarlo prototype, il che non funziona perché thisha 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 thisprecedenza, prototypeposso 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, thisrilevante 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 prototypedefinizione, ma thisha più senso avere la precedenza perché si tratta della nuova istanza creata in quel momento.