使用apply与函数构造函数

时间:2011-10-05 20:12:58

标签: javascript

  

可能重复:
  Use of .apply() with 'new' operator. Is this possible?

我有5或6个表单的变量赋值

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

正如您所看到的,这些构造函数的很大一部分非常相似。如果我可以创建一个允许我做类似的小型通用currying构建器,那将是很好的。

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

我可以用

实现类似的功能
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);
  }
}

但严重ick。我希望能够将前三个已知参数拼接到arguments数组的开头并将其应用于FuncDef,但我因为需要使用new运算符而被挫败。

在有人要求之前,我不能在FuncDef中执行新的操作符强制执行,因为它是由coffeescript类关键字生成的。

2 个答案:

答案 0 :(得分:3)

当然可以做到。这是eval证明有用的一种情况。

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

(从another thread被盗)

答案 1 :(得分:2)

恭喜!您刚刚发现了Javascript中最丑陋的秘密疣之一以及您想要做什么无法完成 1

常见的解决方法是创建包装函数(就像你做的那样)或者重构构造函数来接收列表/对象 2 而不是很多参数。


1 在Harmony(JS的下一个版本)中有多个参数的“...”语法提案,但直到没有办法将可变数量的参数传递给构造函数。

2 当您有大量参数时,传递列表或对象通常是个好主意。它可以防止您意外地混淆订单,并且可以更轻松地处理可选参数(就像您的情况一样)。

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

编辑:刚刚在同一主题上找到了另一个问题:Use of .apply() with 'new' operator. Is this possible?