【问题标题】:Use apply with a function constructor [duplicate]将 apply 与函数构造函数一起使用 [重复]
【发布时间】:2011-12-01 19:15:39
【问题描述】:

可能重复:
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');

如您所见,这些构造函数中有很大一部分非常相似。如果我可以创建一个通用的柯里化构建器来允许我执行以下操作,那就太好了:

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

但是真的很恶心。我希望能够将前三个已知参数拼接到参数数组的开头并将其应用于 FuncDef,但我因需要使用 new 运算符而受阻。

在有人问之前,我不能在 FuncDef 中执行 new-operator 强制,因为它是由 coffeescript 类关键字生成的。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    当然可以。这是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

    【讨论】:

    • 哦,这实际上是一个好点。嗯,想知道这是否有任何范围问题?
    • 作用域应该不是问题,因为clsargs 在传递给newApply 时会随身携带它们的作用域链。
    • 我想知道为什么 (a) 你选择了这个答案,而不是从另一个问题中接受的答案,并且 (b) 你没有投票关闭这个作为重复的答案?
    • @FelixKling 因为虽然我最初明确接受了另一个答案,但“它可以完成”取代了“它不能完成”。这两个答案都非常好,值得一票。它不是重复的,因为它问的是一个微妙的不同的事情,这就是它得到不同答案的原因。
    【解决方案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?

    【讨论】:

      猜你喜欢
      • 2013-10-02
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      相关资源
      最近更新 更多