Is this possible? I am creating a single base factory function to drive factories of different types (but have some similarities) and I want to be able to pass arguments as an array to the base factory which then possibly creates an instance of a new object populating the arguments of the constructor of the relevant class via an array.
In JavaScript it's possible to use an array to call a function with multiple arguments by using the apply method:
namespace.myFunc = function(arg1, arg2) { //do something; }
var result = namespace.myFunc("arg1","arg2");
//this is the same as above:
var r = [ "arg1","arg2" ];
var result = myFunc.apply(namespace, r);
It doesn't seem as if there's anyway to create an instance of an object using apply though, is there?
Something like (this doesn't work):
var instance = new MyClass.apply(namespace, r);
Hacks are hacks are hacks, but perhaps this one is a bit more elegant than some of the others, since calling syntax would be similar to what you want and you wouldn't need to modify the original classes at all:
Now you can do either of these to build an object:
Granted, some may not like modifying the Function object's prototype, so you can do it this way and use it as a function instead:
And then you would call it like so:
So, I hope those are useful to someone - they allow you to leave the original constructor functions alone and get what you are after in one simple line of code (unlike the two lines you need for the currently-selected solution/workaround.
Feedback is welcome and appreciated.
UPDATE: One other thing to note - try creating instances of the same type with these different methods and then checking to see if their constructor properties are the same - you may want that to be the case if you ever need to check the type of an object. What I mean is best illustrated by the following code:
Try that with some of the other hacks and see what happens. Ideally, you want them to be the same type.
CAVEAT: As noted in the comments, this will not work for those constructor functions that are created using anonymous function syntax, i.e.
Unless you create them like this:
The solution I provided above may or may not be useful to you, you need to understand exactly what you are doing to arrive at the best solution for your particular needs, and you need to be cognizant of what is going on to make my solution "work." If you don't understand how my solution works, spend time to figure it out.
ALTERNATE SOLUTION: Not one to overlook other options, here is one of the other ways you could skin this cat (with similar caveats to the above approach), this one a little more esoteric:
Enjoy!
Note that
without any arguments may fail, since the constructor function may rely on the existence of arguments.
will fail in many cases, especially if called on native classes like Date or Number.
I know that "eval is evil", but in this case you may want to try the following:
Simple as that.
(It works the same as
Instance.New
in this blog post)One possibility is to make the constructor work as a normal function call.
The condition on the
if
statement will be true if you callMyClass
as a normal function (including withcall
/apply
as long as thethis
argument is not aMyClass object
).Now all of these are equivalent:
what about a workaround?
So how you can:
Try this:
All the keyword "new" does is pass in a new object to the constructor which then becomes the this variable inside the constructor function.
Depending upon how the constructor was written, you may have to do this:
Update: A comment says this doesn't work if there is a prototype. Try this.