Instantiate a class from its name in a string, without using "Eval" and in Chrome (V75+)

Asked

Viewed 188 times

9

I need to instantiate a class from a string.

Turns out 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) is returning the following error:

Uncaught Typeerror: window[classname] 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 JSFIDDLE

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

  • Did the answer resolve what was in doubt? Do you need something else to be improved? Do you think it is possible to accept it now?

1 answer

5

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

Emergency solution well gambiarra to solve, but solves even and 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 external source directly 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 in the Github for future reference.

The problem is access to the object window that no longer has access to all global objects as it had before. But it does not 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 in the Github for future reference.

So it depends on the context.

To tell you the truth I don’t quite know how the JS treats the constructor, this case that is trying to do I don’t know if it worked one day because it is trying to call the constructor as a normal method.

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

The ideal solution is not to need this, in many scenarios you can do without the name comes from a string. Others might want to rethink whether they need this, almost never need it and it’s just a lazy attempt at a solution that normally exchanges 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 this. And I want to find an answer because it stopped working.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.