4

I use babel.js traspiler to write ES6 code.

I have a string containing class name. I want a class that I can instantiate. How?

I tried:

eval("MyClassName") -> :(
window["MyClassName"] -> :(

Any ideas?

Hubert Łępicki
  • 684
  • 1
  • 7
  • 9
  • What module system are you using with Babel? By default it's common JS, so anything [on this page](https://babeljs.io/docs/usage/modules/#common-default-) would work. – CodingIntrigue Sep 30 '15 at 12:57
  • 1
    Can you elaborate on why you want to do this? Depending on the usecase, there may be options, but overall, as you've seen, the answer is no, without `eval`. – loganfsmyth Sep 30 '15 at 16:41
  • Can you stuff the classes you might want to do it with into an object ahead of time? Is the class you want to do it with a named export of some module? – JMM Oct 01 '15 at 00:41
  • Actually `eval` should work as long as the class is in scope. – Bergi Aug 04 '16 at 05:29
  • Upvote for `-> :(` :))) – Ryall Sep 20 '17 at 21:42

1 Answers1

3

You Can:

Since with BabelJS you have to transpile to an ES5 module loader, it would be as simple as (depending on the module format you've specified at transpile time):

const MyClassName = require("MyClassName");
const obj = new MyClassName();

However this is not ES6, but transpiled ES5. So your code will not work in true ES6 environments.

In an ES6 environment a class is just syntactic sugar for a function, so there is no reason you cannot do:

// Class definition
class MyClassName { }
// Pollute global scope
(global || window).MyClassName = MyClassName;

And load it like so:

const instance = new (window || global)["MyClassName"]();

But in doing so you've just broken the major feature modules give you in the first place.

You Should:

Create a factory class. In the majority of cases, the amount of classes you can instantiate is finite. You should create a factory function which gives you a class instance based on a string:

import MyClassName from "./MyClassName"
class MyFactory {
    static getInstance(value) {
        if(value === "MyClassName") {
            return new MyClassName();
        }
        throw new Error(`Could not instantiate ${value}`);
    }
}

Which would be used as:

import MyFactory from "./MyFactory";
const instance = MyFactory.getInstance("MyClassName");

Obviously you could expand on that to use a Map instead of a string of if statements, but you get the idea.

CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
  • Thanks for that! Very thoughtful response. I just googled the same thing, and I found this thread (classic) and just realized I did not see your notice. I am having a look at the same piece of code that I do not like. This is what you described in "You Should". Well, I'll keep adding to the factory class. – Hubert Łępicki Apr 27 '16 at 16:30
  • Is there a reason why the factory should be a class? Could I not just use a factory function? – Kryten Dec 05 '16 at 14:51
  • No reason at all. Looking back at this answer I wouldn't choose class syntax here myself now. A regular function would work just as well. – CodingIntrigue Dec 05 '16 at 14:53