Metodi di impostazione tramite oggetto prototipo o nel costruttore, differenza? [duplicare]

StackOverflow https://stackoverflow.com/questions/422476

Domanda

    

Questa domanda ha già una risposta qui:

    
            
  •              Uso di 'prototype' vs. 'this' in JavaScript?                                      14 risposte                          
  •     
    

Potresti spiegare la differenza tra i metodi di impostazione nel costruttore e attraverso l'oggetto prototipo? Il codice seguente mostra questi due modi di impostare i metodi: say_hello e say_bye funzionano entrambi bene:

function MessageClass() {
  this.say_bye = function() { alert('see ya'); };
}

MessageClass.prototype.say_hello = function() { alert('hello'); };

x = new MessageClass();
x.say_hello();
x.say_bye();
È stato utile?

Soluzione

foxxtrot e annakata sono entrambi corretti, ma aggiungerò i miei 2 centesimi.

Se utilizzi il prototipo, ogni istanza di " MessageClass " fa davvero riferimento alle stesse funzioni. Le funzioni esistono in memoria solo una volta e sono utilizzate per tutte le istanze. Se si dichiarano i metodi nel costruttore (o altrimenti lo si aggiunge a un'istanza specifica) anziché al prototipo, viene creata una nuova funzione per ogni istanza di MessageClass.

Detto questo, probabilmente non ci sono differenze di prestazioni evidenti nella maggior parte dei casi ed è improbabile che vedrai una differenza di utilizzo della memoria. Andrei con il metodo prototipo a meno che tu non abbia un motivo convincente per fare diversamente. L'unica ragione per cui posso pensare che potresti voler dichiarare un metodo nel costruttore è se hai bisogno di una chiusura. Ad esempio, se si dispone di gestori di eventi o si desidera simulare proprietà private con getter / setter, è possibile:

function MessageClass() {
    var self = this;
    this.clickHander = function(e) { self.someoneClickedMe = true; };

    var _private = 0;
    this.getPrivate = function() { return _private; };
    this.setPrivate = function(val) { _private = val; };
}

EDIT: Poiché si è discusso di come questi oggetti effetti siano stati estesi da un altro oggetto con funzioni assegnate nel costruttore, sto aggiungendo un po 'più di dettaglio. Potrei usare il termine " class " per semplificare la discussione, ma è importante notare che js non supporta le classi (ciò non significa che non possiamo fare un buon sviluppo OO) o che non discuteremo di questo problema.

La maggior parte delle librerie javascript chiamano il costruttore sulla classe base e sulla sottoclasse. (ad esempio Object.extend di Prototype.js) Ciò significa che i metodi assegnati nel costruttore di ciascuno saranno disponibili sugli oggetti risultanti. Tuttavia, se estendi gli oggetti da solo, possono esserci conseguenze impreviste.

Se prendo la MessageClass sopra e la estendo:

function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();

errorMsg = new ErrorMessageClass();

Quindi errorMsg avrà un metodo getPrivate e setPrivate su di esso, ma potrebbero non comportarsi come ci si aspetterebbe. Poiché tali funzioni erano nell'ambito quando sono state assegnate (ovvero in " ErrorMessageClass.prototype = new MessageClass () " non solo i metodi get / setPrivate sono condivisi, la variabile _private viene condivisa anche tra tutte le istanze di ErrorMessageClass. _privare una proprietà statica per ErrorMessageClass, ad esempio:

var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'B'

Allo stesso modo con la funzione clickHandler e la proprietà qualcunoClickedMe:

errorA.clickHandler();
console.log(errorA.someoneClickedMe); // prints 'true'
console.log(errorB.someoneClickedMe); // prints 'true'

Tuttavia, modifica tali definizioni delle funzioni per utilizzare this._private:

this.getPrivate = function() { return this._private; };
this.setPrivate = function(val) { this._private = val; };

e il comportamento delle istanze di ErrorMessageClass diventa più di quello che ti aspetteresti:

errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'B'

Altri suggerimenti

Se si associano metodi per prototipo, JS deve farlo una sola volta e si lega a una classe di oggetti (che lo rende intelligibile per le estensioni OO JS).

Se esegui l'associazione nella classe " " funzione, JS deve fare il lavoro di creazione e assegnazione per ogni singola istanza.

La differenza è quando si ricava una classe da Classe messaggio. Solo i metodi dichiarati sul prototipo saranno disponibili nelle classi secondarie di Message.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top