2011-10-05 14 views
5

Eventuali duplicati:
Use of .apply() with 'new' operator. Is this possible?Utilizzare applicare con un costruttore funzione di

ho 5 o 6 assegnazioni di variabili della forma

var analyteSelection = new TemplatedSelectionContainer($('.analyte-container', this), helpers, optionsTemplate); 
var instrumentSelection = new AssetBackedSelection($('.instrument-container', this), helpers, optionsTemplate, Assets.instruments, 'Instrument'); 
var methodSelection = new AssetBackedSelection($('.method-container', this), helpers, optionsTemplate, Assets.methods, 'Method'); 

Come si può vedere, un una quantità significativa di parti di questi costruttori sono molto simili. Sarebbe bello se potessi creare un piccolo costruttore di accattivarsi generico che mi permettesse di fare qualcosa di simile:

var newSel = selectionContainerBuilder(this, helpers, optionsTemplate) 
var analyteSelection = newSel(TemplatedSelectionContainer, '.analyte-container'); 
var instrumentSelection = newSel(AssetBackedSelection, '.instrument-container', Assets.instruments, 'Instrument'); 
var methodSelection = newSel(AssetBackedSelection, '.method-container', Assets.methods, 'Method'); 

posso raggiungere qualcosa di simile con

var selectionContainerBuilder = function(ctx, helpers, optionsTemplate) { 
    return function(FuncDef, selector, a, b, c, d, e, f) { 
    return new FuncDef($(selector, ctx), helpers, optionsTemplate, a,b,c,d,e,f); 
    } 
} 

Ma sul serio sigh. Vorrei solo essere in grado di unire i primi tre parametri noti all'inizio dell'array degli argomenti e applicarlo a FuncDef, ma mi viene meno la necessità di utilizzare il nuovo operatore.

E prima che qualcuno chieda, non posso eseguire l'applicazione di un nuovo operatore all'interno di FuncDef perché è generato dalla parola chiave della classe coffeescript.

risposta

3

Naturalmente si può fare. Questo è il caso in cui eval risulta essere utile.

function newApply(cls, args) { 
    var argsAsString = []; 
    for (var i = 0, l = args.length; i < l; i++) { 
     argsAsString.push('args[' + i + ']'); 
    } 
    return eval('new cls(' + argsAsString.join(',') + ')'); 
} 

(rubato da another thread)

+0

Oh, è ... un buon punto in realtà. Hmm, mi chiedo se questo ha problemi di scoping? –

+0

Lo scoping non dovrebbe essere un problema, dal momento che 'cls' e' args' prendono le loro catene di scope con loro mentre passano a 'newApply'. – user123444555621

+0

Mi chiedo perché (a) tu scelga questa risposta e non quella accettata dall'altra domanda e (b), non hai votato per chiuderla come duplicato? –

2

Congratulazioni! Hai appena trovato una delle più brutte verruche segrete in Javascript e non puoi fare quello che vuoi fare .

Le soluzioni alternative comuni sono o creando funzioni wrapper (come hai fatto), o ristrutturare le funzioni di costruzione per ricevere liste/oggetti al posto di un sacco di argomenti.


C'è una proposta di "..." sintassi per più argomenti in Armonia (la prossima versione di JS), ma fino allora non c'è modo di passare un numero variabile di argomenti a un costruttore.

Passaggio di una lista o di un oggetto di solito è una buona idea quando si dispone di tonnellate di argomenti. Ti protegge dall'incomprensio- ne dell'ordine per errore e semplifica la gestione dei parametri opzionali (come sembra essere nel tuo caso).

new Foo("arg1", { 
    helpers: helpers, 
    options: optionsTemplate, 
    intruments: Assets.instruments 
}); 

Edit: Appena trovato un'altra domanda su questo stesso argomento: Use of .apply() with 'new' operator. Is this possible?

Problemi correlati