在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);
}
})();
假设你有一个Items构造函数,它吸收了你给它的所有参数:
function Items () {
this.elems = [].slice.call(arguments);
}
Items.prototype.sum = function () {
return this.elems.reduce(function (sum, x) { return sum + x }, 0);
};
你可以用Object.create()创建一个实例,然后用.apply()创建该实例:
var items = Object.create(Items.prototype);
Items.apply(items, [ 1, 2, 3, 4 ]);
console.log(items.sum());
当运行时输出10,因为1 + 2 + 3 + 4 == 10:
$ node t.js
10
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();
Matthew Crumley在CoffeeScript中的解决方案:
construct = (constructor, args) ->
F = -> constructor.apply this, args
F.prototype = constructor.prototype
new F
or
createSomething = (->
F = (args) -> Something.apply this, args
F.prototype = Something.prototype
return -> new Something arguments
)()