Javascript - 使用参数数组创建实例

时间:2011-02-20 02:48:11

标签: javascript

我知道用apply(obj,args)调用带有参数数组的函数的可能性; 有没有办法在创建函数的新实例时使用此功能?

我的意思是这样的:

function A(arg1,arg2){
    var a = arg1;
    var b = arg2;
}

var a = new A.apply([1,2]); //create new instance using an array of arguments

我希望你明白我的意思...... ^^^

感谢您的帮助!

解决!

我得到了正确的答案。为了使答案适合我的问题:

function A(arg1,arg2) {
    var a = arg1;
    var b = arg2;
}

var a = new (A.bind.apply(A,[A,1,2]))();

7 个答案:

答案 0 :(得分:14)

var wrapper = function(f, args) {
    return function() {
        f.apply(this, args);
    };
};

function Constructor() {
    this.foo = 4;
}
var o = new (wrapper(Constructor, [1,2]));
alert(o.foo);

我们接受一个函数和参数,并创建一个函数,将该函数的参数应用于此作用域。

然后,如果您使用new关键字调用它,则会传递一个新的this并返回它。

重要的是括号

new (wrapper(Constructor, [1,2]))

在包装器返回的函数上调用new关键字,其中为

new wrapper(Constructor, [1,2])

在包装函数上调用new关键字。

需要将其包装的原因是,您应用它的this是使用new关键字设置的。需要创建一个新的this对象并将其传递给一个函数,这意味着您必须在函数内调用.apply(this, array)

直播example

或者您可以使用ES5 .bind方法

var wrapper = function(f, args) {
    var params = [f].concat(args);
    return f.bind.apply(f, params);
};

请参阅example

答案 1 :(得分:7)

使用ECMAscript 5,您可以:

function createInstanceWithArguments (fConstructor, aArgs) {
    var foo = Object.create(fConstructor.prototype);
    fConstructor.apply(foo, aArgs);
    return foo;
}

答案 2 :(得分:6)

@Raynos的答案很有效,除了非ES5版本在实例化后缺少构造函数的原型。

这是我更新的cApply方法:

var cApply = function(c) {
  var ctor = function(args) {
    c.apply(this, args);
  };
  ctor.prototype = c.prototype;
  return ctor;
};

可以这样使用:

var WrappedConstructor = cApply(Constructor);
var obj = new WrappedConstructor([1,2,3]);

// or inline like this.    
var obj2 = new (cApply(Constructor))([1,2,3]);

JSFiddle供参考。

答案 3 :(得分:3)

你可以讨论这些功能:

function A(arg1, arg2) {
    // ...
}

function A12() {
    A(1, 2);
}

你甚至可以建一家咖喱厂:

function A_curry() {
    var args = arguments;
    return function () {
        A.apply(null, args);
    };
}

答案 4 :(得分:3)

您可以使用Object.create()构建新实例,然后在该实例上调用构造函数:

var args = [1,2,3];
var instance = Object.create(MyClass.prototype);
MyClass.apply(instance, args);

或单行:

var instance = MyClass.apply(Object.create(MyClass.prototype), args);

但不要忘记return this;中的MyClass这个单行解决方案。

如果你没有Object.create(),那么写一个很简单:

Object.create = function (source){
    var Surrogate = function (){};
    Surrogate.prototype = source;
    return new Surrogate();
};

您可以选择编写Function.newInstance()Function.prototype.newInstance()功能:

Function.newInstance = function (fn, args){
    var instance = Object.create(fn.prototype);
    fn.apply(instance, args);
    return instance;
};

所以var instance = Function.newInstance(MyClass, args);

注意:建议不要覆盖本机类。

答案 5 :(得分:0)

如果您将对象类名称存储在名为className的变量中

,该怎么办?
var className = 'A'

根据this answer here,使用 ECMAScipt5 Function.prototype.bind方法,一切都变得非常干净和简单。

使用一组参数:

new ( Function.prototype.bind.apply( className, arguments ) );

或者使用参数列表:

new ( Function.prototype.bind.call( className, argument1, argument2, ... ) );

一行,不需要包装。

答案 6 :(得分:0)

我遇到了同样的问题,并且还希望保留目标对象的原型属性。看完答案后,我们想出了一个相当简单的解决方案。以为我可能会为任何未来的寻求者分享它:)

// Define a pseudo object that takes your arguments as an array
var PseudoObject = function (args) {
    TargetObject.apply(this, args);
};
// if you want to inherit prototype as well
PseudoObject.prototype = new TargetObject();

// Now just use the PseudoObject to instantiate a object of the the OtherObject
var newObj = new PseudoObject([1, 2, 3]);