4

The problem is that I need to create a new instance of the passed class

Is there a way to rewrite this function, so it could accept any number of arguments?

function createInstance(ofClass, arg1, arg2, arg3, ..., argN){
  return new ofClass(arg1, arg2, arg3, ..., argN);
}

This function should create an instance of the passed class. Example:

var SomeClass = function(arg1, arg2, arg3){
   this.someAttr = arg3;
   .....
}
SomeClass.prototype.method = function(){}

var instance = createInstance(SomeClass, 'arg1', 'arg2', 'arg3'); 

So this should be true.

instance instanceof SomeClass == true  

Right now, I've just limited N to 25, with hope that more arguments are rarely used.

3
  • 1
    Did you read John Resig's article (linked below)? It'll do what you want (although you will need some extra code to do it, of course.) I can't think of any other way to simulate a call to new. The way Resig explains it is what I've seen in all JavaScript libraries with dynamic class generation (MooTools for example.) Commented Aug 13, 2009 at 13:50
  • Thank you, I will go with your solution. Commented Aug 13, 2009 at 13:54
  • This has the correct answer: stackoverflow.com/questions/5054926/… Commented Jul 25, 2012 at 10:49

2 Answers 2

10

The other answers are on the right track, but none of them mention that you have to be aware of the fact that arguments is not an Array. It's a special structure that behaves like an Array.

So before you use it like an Array, you can convert it to one like this:

function createInstance(cls) {
    // This will use the slice function of the Array type, effectively converting
    // the arguments structure to an Array and throwing away the first argument,
    // which is cls.
    var args = Array.prototype.slice.call(arguments, 1);
    return cls.apply(this, args);
}

Sorry, I just copied the code with constructor etc. and didn't think about what it would actually do. I've updated it now to what you want. You'll find that it's calling the constructor without new, so you won't get the same behavior. However, John Resig (author of jQuery) wrote on this very issue.

So based on John Resig's article you've got two ways to solve it. The more elaborate solution will be the most transparent to the user, but it's up to you which solution you choose.


Here is a "perfect" solution if you only intend to support browsers that have the Object.create function (which is a pretty big percentage now compared to three years ago):

function createInstance(cls) {
    var obj = Object.create(cls.prototype);

    var args = Array.prototype.slice.call(arguments, 1);
    cls.apply(obj, args);

    return obj;
}

The resulting objects from both new cls(x) and createInstance(cls, x) should be identical.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, my question wasn't clear enough, the problem is that I need a new instance of obj, so your answer doesn't solve my problem, but upvoted for mention that arguments in not an Array.
I understand your question better now. Read my update for how to solve your problem.
I'd appreciate an explanation for -1, especially considering that this is the only answer that, to the best of my knowledge, works (when taking John Resig's change into consideration.) I see someone finally brought up eval as a solution, but I wouldn't touch that with a stick, I'm afraid.
4

There is always an arguments array

2 Comments

I know about it, please give an example how would you use it to rewrite this function.
Could you give a concrete example? Do you have to pass all args in the constructor? Doesn't Djko's Answer work? stackoverflow.com/questions/1271657/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.