In JavaScript, I want to create an object instance (via the new
operator), but pass an arbitrary number of arguments to the constructor. Is this possible?
What I want to do is something like this (but the code below does not work):
function Something(){
// init stuff
}
function createSomething(){
return new Something.apply(null, arguments);
}
var s = createSomething(a,b,c); // 's' is an instance of Something
The Answer
From the responses here, it became clear that there's no built-in way to call .apply()
with the new
operator. However, people suggested a number of really interesting solutions to the problem.
My preferred solution was this one from Matthew Crumley (I've modified it to pass the arguments
property):
var createSomething = (function() {
function F(args) {
return Something.apply(this, args);
}
F.prototype = Something.prototype;
return function() {
return new F(arguments);
}
})();
Matthew Crumley's solutions in CoffeeScript:
or
See also how CoffeeScript does it.
s = new Something([a,b,c]...)
becomes:
If your environment supports ECMA Script 2015's spread operator (
...
), you can simply use it like thisNote: Now that the ECMA Script 2015's specifications are published and most JavaScript engines are actively implementing it, this would be the preferred way of doing this.
You can check the Spread operator's support in few of the major environments, here.
You can't call a constructor with a variable number of arguments like you want with the
new
operator.What you can do is change the constructor slightly. Instead of:
Do this instead:
Or if you must use an array:
It's also intresting to see how the issue of reusing the temporary
F()
constructor, was addressed by usingarguments.callee
, aka the creator/factory function itself: http://www.dhtmlkitchen.com/?category=/JavaScript/&date=2008/05/11/&entry=Decorator-Factory-AspectThis constructor approach works both with and without the
new
keyword:It assumes support for
Object.create
but you could always polyfill that if you're supporting older browsers. See the support table on MDN here.Here's a JSBin to see it in action with console output.