javascript – Instantiate a class from its name in a string, without using "eval" and in Chrome (v75+)

Question:

I need to instantiate a class from a string .

It turns out that for some reason it doesn't work the way I used to:

class MinhaClasse{
    meuMetodo(){
    alert('Método Funciona!');
  }
}

let nome_classe = 'MinhaClasse';
let nome_metodo = 'meuMetodo';

// var obj =  new MinhaClasse(); // instanciando diretamente funciona
var obj =  new window[nome_classe](); // instanciando por string não funciona
obj[nome_metodo]();

In Chrome (v75) it is returning the following error:

Uncaught TypeError: window[class_name] is not a constructor

 class MinhaClasse{ meuMetodo(){ alert('Método Funciona!'); } } let nome_classe = 'MinhaClasse'; let nome_metodo = 'meuMetodo'; // var obj = new MinhaClasse(); // instanciando diretamente funciona var obj = new window[nome_classe](); // instanciando por string não funciona obj[nome_metodo]();

I also made a JSFIDLE

NOTE: Observe the application in current browsers (Ex: Chrome v75 or higher), as the solutions given in other answers here are similar to the method I used (described above) and do not work in current browsers .

Answer:

I actually saw this happen. This worked and it doesn't anymore. I can't say yet if it really worked without being official or if they irresponsibly broke compatibility. It's not just Chrome that has changed. I admit that the solution could be being used for a flaw and not for being documented.

An emergency solution that is quite a gambiarra to solve, but it does solve it and it is not so absurd considering that the code is on the client side in most cases (in Node I would be more afraid if the value of the variable used with the name comes from a direct external source or indirectly).

 class MinhaClasse{ meuMetodo() { alert('Método Funciona!'); } } let nome_classe = 'MinhaClasse'; let nome_metodo = 'meuMetodo'; var obj = eval("new " + nome_classe + "()"); obj[nome_metodo]();

I put it on GitHub for future reference .

The problem is the access to the window object that no longer has access to all global objects as it used to. But it doesn't happen in every situation:

function sayHello() {
    console.log('Hello');
}

window["sayHello"]();
this["sayHello"]();
self["sayHello"]();
//top["sayHello"](); //tem problemas de permissão
globalThis["sayHello"]();

I put it on GitHub for future reference .

So it depends on the context.

To tell you the truth I don't know how JS treats the constructor, this case that you're trying to do I don't know if it ever worked because it's trying to call the constructor as a normal method.

I would at least try to sanitize a bit before using the content. This makes the code very dynamic.

The ideal solution is not to need this, in many scenarios you can do it without the name coming from a string . Others should perhaps rethink if they need it, it almost never does and it's just a lazy attempt at a solution that usually trades robustness and performance for less typing and creation time.

I'm still trying to find a better solution. I found some that just hide the eval() . I found at least one that is too complicated to use like that. And I want to find an answer why it stopped working.

Scroll to Top