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);
}
})();
You could move the init stuff out into a separate method of
Something
's prototype:@Matthew I think it's better to fix the constructor property also.
An improved version of @Matthew's answer. This form has the slight performance benefits obtained by storing the temp class in a closure, as well as the flexibility of having one function able to be used to create any class
This would be used by calling
applyCtor(class, [arg1, arg2, argn]);
If your target browser doesn't support ECMAScript 5
Function.prototype.bind
, the code won't work. It is not very likely though, see compatibilty table.since ES6 this is possible through the Spread operator, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Apply_for_new
This answer was already, sort of given in comment https://stackoverflow.com/a/42027742/7049810, but seems to have been missed by most
This answer is a little late, but figured anyone who sees this might be able to use it. There is a way to return a new object using apply. Though it requires one little change to your object declaration.
For the first
if
statement to work intestNew
you have toreturn this;
at the bottom of the function. So as an example with your code:Update: I've changed my first example to sum any number of arguments, instead of just two.