在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()。然而,人们对这个问题提出了许多非常有趣的解决方案。

我更喜欢的解决方案是来自Matthew Crumley的这个(我修改了它来传递arguments属性):

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

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

当前回答

function createSomething() {
    var args = Array.prototype.concat.apply([null], arguments);
    return new (Function.prototype.bind.apply(Something, args));
}

如果您的目标浏览器不支持ECMAScript 5。绑定,代码将无法工作。这是不太可能的,但见兼容性表。

其他回答

你为什么要把事情弄得这么复杂。在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}
function createSomething() {
    var args = Array.prototype.concat.apply([null], arguments);
    return new (Function.prototype.bind.apply(Something, args));
}

如果您的目标浏览器不支持ECMAScript 5。绑定,代码将无法工作。这是不太可能的,但见兼容性表。

其实最简单的方法是:

function Something (a, b) {
  this.a = a;
  this.b = b;
}
function createSomething(){
    return Something;
}
s = new (createSomething())(1, 2); 
// s == Something {a: 1, b: 2}
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();

任何函数(甚至是构造函数)都可以接受数量可变的参数。每个函数都有一个“arguments”变量,可以使用[].slice.call(arguments)转换为数组。

function Something(){
  this.options  = [].slice.call(arguments);

  this.toString = function (){
    return this.options.toString();
  };
}

var s = new Something(1, 2, 3, 4);
console.log( 's.options === "1,2,3,4":', (s.options == '1,2,3,4') );

var z = new Something(9, 10, 11);
console.log( 'z.options === "9,10,11":', (z.options == '9,10,11') );

上述测试产生以下输出:

s.options === "1,2,3,4": true
z.options === "9,10,11": true