2011-10-05 16 views
5

Duplicar posibles:
Use of .apply() with 'new' operator. Is this possible?uso se aplican con un constructor función

tengo 5 o 6 asignaciones de variables de la 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'); 

Como se puede ver, una cantidad significativa de parte de estos constructores son muy parecidos. Sería bueno si pudiera crear un pequeño constructor currificación genérico que permita que haga algo como:

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'); 

puedo lograr algo similar 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); 
    } 
} 

Pero en serio ick. Me gustaría simplemente poder empalmar los primeros tres parámetros conocidos al principio de la matriz de argumentos y aplicarla a FuncDef, pero me está frustrando la necesidad de usar el nuevo operador.

Y antes de que alguien pregunte, no puedo hacer la aplicación de un nuevo operador dentro de FuncDef porque está siendo generado por la palabra clave de la clase coffeescript.

Respuesta

3

Por supuesto que se puede hacer. Este es el único caso en el que eval resulta útil.

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(',') + ')'); 
} 

(robado de another thread)

+0

Oh, eso es ... un buen punto de realidad. Hmm, me pregunto si esto tiene algún problema de alcance? –

+0

El alcance no debería ser un problema, ya que 'cls' y' args' toman sus cadenas de alcance con ellos a medida que pasan a 'newApply'. – user123444555621

+0

Me pregunto por qué (a) eliges esta respuesta y no la aceptada de la otra pregunta y (b), ¿no votaste para cerrar esto como un duplicado? –

2

¡Enhorabuena! Acabas de encontrar una de las verrugas secretas más feas en Javascript y lo que quieres hacer no se puede hacer.

Las soluciones comunes están creando ya sea funciones de contenedor (como lo hizo) o la reestructuración de las funciones constructoras para recibir las listas/objetos en lugar de un montón de argumentos.


Existe una propuesta de "..." sintaxis para varios argumentos en Harmony (la próxima versión de JS), pero hasta el entonces no hay manera de pasar un número variable de argumentos a un constructor

Pasando una lista o un objeto es generalmente una buena idea cuando se tiene un montón de argumentos. Le protege de mezclar el orden por accidente y hace que sea más fácil manejar parámetros opcionales (como parece ser en su caso).

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

Editar: Sólo se encontró otra pregunta sobre el mismo tema: Use of .apply() with 'new' operator. Is this possible?

Cuestiones relacionadas