【问题标题】:Use of .apply() with 'new' operator. Is this possible?将 .apply() 与“new”运算符一起使用。这可能吗?
【发布时间】:2010-12-09 01:44:33
【问题描述】:

在 JavaScript 中,我想创建一个对象实例(通过 new 运算符),但将任意数量的参数传递给构造函数。这可能吗?

我想做的是这样的(但下面的代码不起作用):

function Something(){
    // init stuff
}
function createSomething(){
    return new Something.apply(null, arguments);
}
var s = createSomething(a,b,c); // 's' is an instance of Something

答案

从这里的响应中可以清楚地看出,没有内置方法可以使用 new 运算符调用 .apply()。然而,人们提出了一些非常有趣的解决方案来解决这个问题。

我首选的解决方案是this one from Matthew Crumley(我已对其进行了修改以传递arguments 属性):

var createSomething = (function() {
    function F(args) {
        return Something.apply(this, args);
    }
    F.prototype = Something.prototype;

    return function() {
        return new F(arguments);
    }
})();

【问题讨论】:

  • [Matthew Crumley 的解决方案][1] 在 CoffeeScript 中:construct = (constructor, args) -> F = -> constructor.apply this,args F.prototype = constructor.prototype new F createSomething = ( ()-> F = (args) -> Something.apply this.args F.prototype = Something.prototype return -> new Something 参数)() [1]: stackoverflow.com/questions/1606797/…
  • 我认为这个线程的要点是new 做了两件事:(i) 设置原型,(ii) 将 this 设置为所述对象/原型的构造函数应用组合。您可以使用Object.create() 来实现这一点,也可以通过对Object.create() 采取自己的看法并使用闭包捕获上下文。
  • 我通过将类作为参数传递给外部函数来概括它。所以这基本上是一个工厂工厂。
  • @Pumbaa80 的答案似乎是更好的解决方案,ES6 Traceur 也使用它来填充 spread 运算符。 =) 在 Chrome 中它也快一点:jsperf.com/dynamic-arguments-to-the-constructor
  • 谁能解释一下为什么这家伙不能像var s = new Something(a,b,c)那样做?我无法得到它:/

标签: javascript oop class inheritance constructor


【解决方案1】:
function FooFactory() {
    var prototype, F = function(){};

    function Foo() {
        var args = Array.prototype.slice.call(arguments),
            i;     
        for (i = 0, this.args = {}; i < args.length; i +=1) {
            this.args[i] = args[i];
        }
        this.bar = 'baz';
        this.print();

        return this;
    }

    prototype = Foo.prototype;
    prototype.print = function () {
        console.log(this.bar);
    };

    F.prototype = prototype;

    return Foo.apply(new F(), Array.prototype.slice.call(arguments));
}

var foo = FooFactory('a', 'b', 'c', 'd', {}, function (){});
console.log('foo:',foo);
foo.print();

【讨论】:

    【解决方案2】:

    作为一个较晚的答案,我只是将这里作为一个更完整的解决方案使用这里已经概述的许多原则。

    Implements.js

    为了让您开始,这里是一个基本用法:

    var a = function(){
        this.propa = 'a';
    }
    var b = function(){
        this.propb = 'b'
    }
    var c = Function.Implement(a, b); // -> { propa: 'a', propb: 'b' }
    

    【讨论】:

      【解决方案3】:

      你为什么要把事情搞得这么复杂。在 new 之后使用匿名函数,该函数返回带有参数的构造函数。

      function myConstructor(a,b,c){
          this.a = a;
          this.b = b;
          this.c = c;
      }
      
      var newObject = new myConstructor(1,2,3);   // {a: 1, b: 2, c: 3}
      
      var myArguments = [1,2,3];
      var anotherObject = new function(){
          return myConstructor.apply(this,myArguments);
        }; // {a: 1, b: 2, c: 3}
      

      【讨论】:

        【解决方案4】:

        这不应该吗?半醒,没仔细看。

        var Storage = undefined;
        
        return ((Storage = (new Something(...))) == undefined? (undefined) : (Storage.apply(...)));
        

        【讨论】:

        • 我喜欢它是如何被超级否决的,即使它与最佳答案基本相同。
        【解决方案5】:

        This 可能是解决这个问题的一种低效方式,但我认为这对我来说足够简单理解。

        function createSomething(){
            // use 'new' operator to instantiate a 'Something' object
            var tmp = new Something(); 
        
            // If the interpreter supports [JavaScript 1.8.5][2], use 'Object.create'
            // var tmp = Object.create(Something.prototype); 
        
            // calling the constructor again to initialize the object
            Something.apply(tmp, arguments); 
            return tmp;
        }
        

        【讨论】:

          【解决方案6】:
          function F(a){this.a=a}
          Z=F;
          f=Function('return new function '+F.name+' ()
          {return  Z.apply(this,[1]) } ').call()
          console.log(f)
          
          function F(a){this.a=a} 
          f= new function(){return F.apply(this,[1])} 
          console.log(f) 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-13
            • 1970-01-01
            • 2020-10-21
            • 1970-01-01
            • 2019-05-26
            相关资源
            最近更新 更多