2

I'm trying to create a ES class definition from a string.

const def = "class M {}";
// ???
const inst = new M();

I'm not in Window, so I can't use DOM based approaches like putting it in script tags. I've tried a few approaches with function() and eval() but no real success.

The closest I've come is a pretty ugly factory approach.

const M = new Function('return new class M { test; constructor(){ this.test = "Hello"; } tfun(input){ return input + 7; } }');

const inst = new M();
inst.test; // Hello
inst.tfun(5); // output: 12

This doesn't call the constructor with params though.

const M = new Function('return new class M { test; constructor(param){ this.test = param; } tfun(input){ return input + 7; } }');

const inst = new M("Hello");
inst.test; // undefined 
Randy Buchholz
  • 233
  • 3
  • 8
  • 1
    See this [Running Dynamic Javascript code](https://stackoverflow.com/questions/22340975/running-dynamic-javascript-code) – Hatem Mohamed Jul 31 '20 at 21:15
  • 1
    I tried a few approaches from that arena, but it seems like `eval` doesn't put the class in the global scope or have it persist outside of the `eval` lifetime. Similar to my comment on @Mureinik answer, when `eval` runs it seems the class definition is available in that context, but once `eval` exists the definition is disposed. I need it to ba available after the creating code is done. – Randy Buchholz Jul 31 '20 at 21:39
  • Is this of any use? https://stackoverflow.com/questions/1366127/how-do-i-make-javascript-object-using-a-variable-string-to-define-the-class-name – Cat Jul 31 '20 at 21:50

1 Answers1

2

One way to achieve this is to add the text that instantiates the class to the string and only then eval it:

const def = 'class M {}';
const instantiator = def + '; new M();';

const m = eval(instantiator);

EDIT:
To follow-up on the comment, if you want the class itself, it's even simpler - just add its name to the string you're evaluating:

const def = 'class M {}';
const statement = def + '; M;';

const M = eval(statement);
const m = new M(); // This now works!
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • That's much cleaner, but what I really need to do is create the class itself not just instances. I am creating instances using `Reflect.construct(classDef, [])` in many places. – Randy Buchholz Jul 31 '20 at 21:29
  • 1
    @RandyBuchholz If you want the class itself, I think it's even simpler - see my edit above – Mureinik Jul 31 '20 at 21:33