将 .apply() 与“new”运算符一起使用。这可能吗?

Posted

技术标签:

【中文标题】将 .apply() 与“new”运算符一起使用。这可能吗?【英文标题】:Use of .apply() with 'new' operator. Is this possible? 【发布时间】: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]: ***.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)那样做?我无法得到它:/ 【参考方案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) 

【讨论】:

以上是关于将 .apply() 与“new”运算符一起使用。这可能吗?的主要内容,如果未能解决你的问题,请参考以下文章

将placement new 与存储类一起使用时的额外构造

`@apply` 不能与 `.text-md` 一起使用

如何在bind()中处理'new'运算符?

不能将 `git mergetool` 与 `git am` 或 `git apply` 或 `patch` 一起使用

Array.apply(null,{length:20})与new Array(20)的区别

错误“不能将 'new' 与类型缺少调用或构造签名的表达式一起使用。”导入 Esri 类型时