So che ci sono domande simili come questa, ma voglio vedere se quelle risposte sono ancora valide date le ottimizzazioni nei nuovi motori Javascript.Funzioni all'interno del costruttore vs prototipo
A mio parere, il più grande vantaggio sulla definizione funzioni all'interno del costruttore è che si può facilmente evitare di dover conoscere il valore di 'questo' parola chiave:
var Person = function() {
var self = this;
self.firstName = null;
self.lastName = null;
self.fullName = function() {
return self.firstName + self.lastName;
};
};
Questo approccio è consigliato da Knockout Managing 'this'. Questo è un grande vantaggio, specialmente quando il codice viene modificato da molti sviluppatori in quanto è molto semplice da capire e da usare.
L'altro approccio sarebbe quello di utilizzare il prototipo dell'oggetto:
var Person = function() {
this.firstName = null;
this.lastName = null;
};
Person.prototype.fullName = function() {
return this.firstName + this.lastName;
};
In questo caso ci sono vantaggi prestazionali perché funzioni oggetti viene creato quando. Tuttavia il problema principale che ho con esso è che potrebbe essere complicato gestire la parola chiave "this". L'esempio sopra è molto semplice, ma se si hanno gestori di eventi, per chiamate Ogni, chiamate jQuery each(), metodi chiamati da contesti diversi, ecc., È facile fare un cattivo uso di questo.
Naturalmente, se si capisce come "questo" funzioni e siano consapevoli di come vengono chiamati i metodi, non si dovrebbero avere molti problemi. Tuttavia, nella mia esperienza, questo richiede tempo ed è soggetto a errori, specialmente quando il codice è creato da molti sviluppatori.
So che i nuovi motori JS, come V8, applicano le ottimizzazioni ai casi in cui si dichiarano funzioni all'interno del costruttore mediante la creazione di classi nascoste: How the V8 engine works?.
Quindi la mia domanda è, date queste ottimizzazioni fatte dai nuovi motori JS e la complessità di dover gestire la parola chiave "this", ha ancora senso utilizzare l'approccio basato sul prototipo? Cosa avrei perso usando l'approccio di mettere tutto all'interno del costruttore?
UPDATE 1:
Ho appena fatto un micro-benchmark su Chrome (versione 42). Creo oggetti 1M con funzioni all'interno del costruttore e funzioni in prototipo. E 'un oggetto molto semplice con due variabili e tre funzioni ed i risultati sono simili:
Functions inside constructor: 1.91 seconds
Functions in prototype: 1.10 seconds
Suona come anche con tali ottimizzazioni in V8 è ancora 73% più velocemente. Tuttavia questo era un micro-benchmark. Non sono sicuro che questa sarà una grande differenza nelle applicazioni del mondo reale.
UPDATE 2:
ho anche preso uno sguardo al consumo di memoria e non ci sono grandi differenze pure. Per le funzioni costruttori interna:
Shallow size: 64,000,120
Retained size: 336,001,128
Per le funzioni di prototipo:
Shallow size: 40,000,000
Retained size: 40,000,000
Entrambi ottimizzazioni con classe di nascosto che non sono buone o mi manca qualcosa. Sto usando il codice monomorfico (costruttori senza argomenti) come suggerito dal V8, ma non sono sicuro se sto facendo qualcosa di sbagliato.
UPDATE 3:
Ecco il link del test che ho fatto nel caso in cui qualcuno può indicare qualcosa che non va in là: http://jsperf.com/dg-constructor-vs-prototype
FWIW, ho aggiunto un terzo banco di prova, il "POJO" che non utilizza prototipo o la "nuova" parola chiave, semplicemente crea un oggetto con metodi pubblici e variabili private. È paragonabile nelle prestazioni all'esempio del costruttore. In entrambi i casi, il metodo prototipo è costantemente più veloce, anche se con la complessità aggiunta. http://jsperf.com/dg-constructor-vs-prototype/2 –
Grazie Scott. Sì, sembra che in questo momento il modo più efficiente sia usare il prototipo. È un peccato perché amo la semplicità di assegnare "questo" a "sé" ed essere sicuro che il "sé" punta all'oggetto invece di dover pensare a cosa "questo" indica. – dgaviola
Sì, sono completamente d'accordo. Per oggetti semplici (senza ereditarietà), l'uso di 'prototype' non è altro che una micro ottimizzazione, con l'inconveniente di dover comprendere e gestire attentamente l'uso di' this'. –