0

I have a JS class that takes in several arguments:

var MyClassName = function(arg1, arg2, arg3){ // Do stuff };

I have a String that represents the class's name, and an array of arguments.

var class = "MyClassName"
var args = ["1", "2", "3"]

Using the String of the class name and the array of arguments, how can I instantiate the class? Prototype Bind/apply seems to have some relevance, but I can't quite figure out how this all works together. I've also tried using window["MyClassName"], but that throws an undefined error. Any suggestions?

ph34r
  • 93
  • 1
  • 12
  • possible duplicate of [What techniques can be used to define a class in JavaScript, and what are their trade-offs?](http://stackoverflow.com/questions/387707/what-techniques-can-be-used-to-define-a-class-in-javascript-and-what-are-their) – RafaelKr Jun 01 '15 at 23:19
  • Sorry, then I didn't unterstand your answer. – RafaelKr Jun 01 '15 at 23:25
  • To clarify, I'm trying instantiate a new instance of a class based on a string of the class's name. The class takes several arguments, but I only want to pass it an array or arguments. – ph34r Jun 01 '15 at 23:26
  • Edit: Wrong answer again.. I should go to bed. – RafaelKr Jun 01 '15 at 23:32
  • Can you explain the reason for doing this? That might help someone offer a better solution. – Yogi Jun 01 '15 at 23:51
  • Good call Robert, I have a very lightweight framework that manages several plugins. I want the framework to be able to be able to control a set of common functions available within the plugins (ie start, stop, reload). To do this, I'm trying to create a plugin registration function on the framework that takes a json array of class names for the plugins and the arguments those classes require. My hope was to be able to iterate that json array and instantiate all of the classes. – ph34r Jun 02 '15 at 00:05
  • Have a look at the edit of my answer, please. – RafaelKr Jun 02 '15 at 14:41

3 Answers3

1

You can use eval:

var a = eval("new " + className + " ( " + arguments.toString() + ")");

Example:

JSFIDDLE: https://jsfiddle.net/s40ave7r/

function A(a1,a2,a3) {
    this.a1 = a1;
    this.a2 = a2;
    this.a3 = a3;
}

var className = "A";
var arguments = [1,2,3];

var a = eval("new " + className + " ( " + arguments.toString() + ")");

console.log(a); // A {a1:1, a2:2, a3:3}

Note:

Using eval in general is a bad idea. If you can try to avoid it. These are some problems related to eval:

  1. Improper use of eval opens up your code for injection attacks
  2. Debugging can be more challenging (no line numbers, etc.)
  3. eval'd code executes more slowly (no opportunity to compile/cache eval'd code)

Solution 2

Other solution is to attach the class definition to an object. For example, when you define a class in the global scope this is attached by default to the window object in the browser, or to the global object in node. So you can do :

Browser

function MyClass() {}
new window["MyClass"](arg1, arg2..);

Node

function MyClass() {}
new window["MyClass"](arg1, arg2..);
Giuseppe Pes
  • 7,772
  • 3
  • 52
  • 90
1

You can define your 'class' as

window.MyClassName = function( arg1, arg2, ... ) {
    this.arg1 = arg1;
    //...
};

then you can call it with

var instance = new window['MyClassName']( arg1, arg2, ... ) 

or with

var instance = new window.MyClassName( arg1, arg2, ... );

or better don't use window, use an own object.

var classes = {
    MyClassName: function( arg1, arg2, ... ) {
        this.arg1 = arg1;
        //...
    }
};

var instance = new classes.MyClassName( arg1 );

Edit: You said window["MyClassName"] didn't work, but if you define a 'class' in the global scope, then you can call it like this. Can you please add the error you meant?

function testClass( arg1 ) {
    this.foo = arg1;
}

var instance = new window['testClass']( 'bar' );
console.log( instance.foo ); // The output will be bar

This code is working, but probably you forgot the 'new'. If you try this without the 'new', then it throws this error at Chrome:

Uncaught TypeError: Cannot read property 'foo' of undefined
RafaelKr
  • 915
  • 8
  • 18
0

Thank you all for the wonderful suggestions. I combined part of the answers here in addition to this SO answer:

var className = new window['MyClassName'] var instantiatedClass = className.bind.apply(className, [null, arg1, arg2, ...]);

Community
  • 1
  • 1
ph34r
  • 93
  • 1
  • 12