risposta embedded seguito in UPDATE 2/RISPOSTADeathmatch: self executing funzione anonima -confrontarli- "nuova funzione"
Grazie a Giuseppe per avermi aiutato a trovare la risposta (anche se non mi piace =) .
domanda iniziale
Pur facendo qualche ricerca sulle migliori pratiche quando si utilizza Namepsaces in JavaScript, mi sono imbattuto in questa definizione del "modello Modello": http://yuiblog.com/blog/2007/06/12/module-pattern/.
In genere uso questo schema da quando l'ho visto in YUI2 anni fa e questo articolo offre una buona panoramica del concetto. Ma ciò a cui non tocca è il motivo per cui "Auto Eseguendo funzioni anonime" vengono usate al posto di "nuova funzione". Questo è stato chiesto nei commenti, ma non è stato ben descritto dall'autore. Dato che questo articolo ha 4 o più anni (e non ho trovato la risposta altrove online) ho pensato di portarlo qui.
È già all'interno di una chiusura, quindi? (vedi: Why is this function wrapped in parentheses, followed by parentheses? che inoltre non risponde alla mia domanda =).
Supponendo che il seguente codice di impostazione ..
var MyNamespace = window.MyNamespace || {};
Quale di questi è preferito e perché?
MyNamespace.UsingNew = new function() {
var fnPrivate = function() {
return "secrets1";
};
this.property = "value1";
this.method = function() {
return "property = " + this.property + ' ' + fnPrivate();
}
};
MyNamespace.UsingSelfEx = (function() { //# <- Added "pre-parens" suggested by chuckj
var fnPrivate = function() {
return "secrets2";
};
var fnReturn = {};
fnReturn.property = "value2";
fnReturn.method = function() {
return "property = " + this.property + ' ' + fnPrivate();
}
return fnReturn;
})();
UPDATE:
Sembra che, come jQuery, tutti i bambini freschi stanno usando "self executing funzioni anonime" (SEAF)! Ma proprio non capisco, perché trovo molto più pulito usare l'approccio .UsingNew mentre esponi le funzioni pubbliche alla definizione (piuttosto che al di sotto in un ritorno che deve essere mantenuto separatamente o essere costretto a usare l'oggetto inline notazione).
L'argomento per non aver bisogno "che = questo" non regge per una serie di ragioni:
- Al fine di evitare "var = che questo" si finisce o fare una " var obj "più un'istruzione return (che deve gestire una definizione separata di ciò che è pubblico) o essere costretta a utilizzare la notazione dell'oggetto inline (return {1,2,3}) per le proprietà/i metodi pubblici.
- Si può sempre creare una variabile privata di "var that = this" nella parte superiore della classe/spazio dei nomi e utilizzare "that" dappertutto.
Ora ... Suppongo che il mio stile di sviluppo possa rendere molto più facile la gestione del modello .UsingNew. Le mie funzioni "private" sono quasi sempre di natura "statica", quindi devo comunque passare nel contesto (supplendo alla necessità di "questo"). Ho anche preso l'abitudine di usare uno spazio dei nomi di "abbreviazione", quindi quando ho bisogno di accedere a "questo" mi riferisco semplicemente all'oggetto completo tramite lo spazio dei nomi "abbreviazione" piuttosto che tramite il suo percorso completo. Es .:
var PrivateFunct = function() {
var rThis = Cn._.val; //# The abbreviated form of Cn.Renderer.Form.Validation
//...
};
o se si tratta di una funzione statica privato ...
var PrivateStaticFunct = function(oContext) {
//...
};
Altri poi le ragioni sopra esposte, che personalmente trovo l'approccio .UsingNew molto più leggibile nella fonte.Ho una codebase piuttosto ampia che utilizza il pattern .UsingNew qui: http://code.google.com/p/cn-namespace/source/browse/Cn.Web/js/Cn/ con il Validation functionality probabilmente il modo più semplice per ottenere la vostra testa in 1 lettura veloce attraverso. Uso anche alcune funzioni SEAF (vedi ErrorMessages.js.aspx) ma solo quando hanno senso.
Non riesco a immaginare di dover mantenere resi separati per esporre le interfacce pubbliche in fondo! Che schifo!
Ora, non fraintendetemi, ci sono un certo numero di posti in cui un SEAF è molto utile al fine di far rispettare la chiusura, ma personalmente penso che sia abusato all'interno degli oggetti.
UPDATE 2:
Su ulteriore riflessione (e grazie a una discussione estesa con Giuseppe sotto la sua risposta) non sembra esserci alcune regole che possono essere applicati a questo DEATHMATCH:
Per Douglas Crockford (vedi: JS we hardly new Ya) Anonymous funzioni non dovrebbero mai utilizzare la "nuova" parola chiave perché:
- E 'più veloce di utilizzare un oggetto l curartene.
- Usando il nuovo per invocare la funzione, l'oggetto rimane su un oggetto prototipo senza valore. Ciò spreca memoria senza vantaggi offensive. Se non usiamo il nuovo, non conserviamo l'oggetto prototipo sprecato nella catena. (NOTA: le chiamate di prototipo arrivano dopo la definizione del costruttore, e come SEAF o "nuove" funzioni anonime vengono lanciate imminentemente non è possibile utilizzare prototipo con esse)
- Richiede meno codice per utilizzare un oggetto letterale. (anche se è vero, non sono d'accordo perché odio la notazione letterale dell'oggetto, preferirei molto usarla; è piuttosto allora, è più leggibile).
- Non è mai una buona idea mettere direttamente nuovo davanti alla funzione. Ad esempio, la nuova funzione non offre alcun vantaggio nella costruzione di nuovi oggetti.
Così sembra la carne e le patate della questione è questo: SEAF di sono preferibili per var obj = new function() {...};
a causa di velocità e meno overhead (nessun prototipo oggetto non necessari). Ciò che devi sopportare è il fatto che sei costretto a usare la notazione letterale dell'oggetto (quindi, piuttosto che i suoi membri pubblici) o mantenere un elenco separato di oggetti pubblici in un oggetto di ritorno.
SEAF non è consigliabile quando si intende che la funzione funzioni come costruttore di oggetti come instanceof
non funzionerà come previsto (vedere: creating objects from JS closure: should i use the “new” keyword?).
RISPOSTA:
- Se si tratta di una funzione anonima destinata a funzionare come un Singleton/Global statico instance, utilizzare SEAF.
Se si intende che funzioni come
Constructor
(per rappresentare potenzialmente più oggetti) o si utilizza .prototype, utilizzare una definizione di funzione "standard" e invocare con "nuovo", ad es.:function PseudoClass1() {}
var PseudoClass2 = function() {};
var myClass1 = new PseudoClass1();
var myClass2 = new PseudoClass2();
devo dire, io non sono contento di questa risposta;) trovo il modello .UsingNew MOLTO più leggibile nel codebase, ma è più lento e utilizza più memoria di SEAF per il fatto che th Il riferimento del prototipo inutilizzato viene istanziato e lasciato nella catena degli oggetti.
(in ritardo alla festa lo so ..) Un sacco di roba interessante ... dato che si preferisce con forza l'UsingNew I don Penso che il prototipo inutilizzato sia una ragione sufficiente per cambiare il tuo approccio ... è una quantità minima di memoria (per ragioni di comparazione, è molto più minimale della quantità che i programmatori che usano il modello di modulo sono disposti a sacrificare non usando prototipi.) –
In termini di approccio alla funzione anonima, forse sembrerebbe più leggibile se si richiamasse la variabile di ritorno "self" invece di qualcosa come "fnReturn". Si potrebbe anche passare qualsiasi oggetto vuoto alla funzione e avere un "sé" come parametro; quindi assecondare la dichiarazione di ritorno e l'uso di "sé" invece di "questo", il corpo della funzione sarebbe identico al primo esempio. –
Si dovrebbe [sicuramente non usare 'nuova funzione'] (http://stackoverflow.com/a/10406585/1048572) – Bergi