10

I would like to get an object from its name in Javascript. I'm working on an application which will need to load up some different context, I'm trying so to load different classes with the "inherit" jquery plugin. Everything works just fine, excepts that, when I need to instanciate a class I can't because I've only the name of the class and not the object directly.

Basically, I would like to find something like 'getClass(String name)'. Does anyone could help me ?

Celero
  • 445
  • 2
  • 6
  • 19
  • Ok, that's stupid, but using the 'eval()' function on the name of my object do the trick... Sorry for this useless post... – Celero Apr 13 '11 at 08:19

4 Answers4

19

Don't use eval().

You could store your classes in a map:

var classes = {
   A: <object here>,
   B: <object here>,
   ...
};

and then just look them up:

new classes[name]()
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 2
    Why does using 'eval()' is wrong ? I can't do it like this, my "classes" are generic and must be load in some particular context, I can't load up a map like this... – Celero Apr 13 '11 at 08:52
  • @Celero: Because `eval()` can be used to execute arbitrary code which can be a security risk. It provides much more power than you need. Why can't you use a map? What do you mean with generic and which context are you talking about? If you provide more information, we can helo you better. – Felix Kling Apr 13 '11 at 08:57
  • I was entierly wrong, your tricks can be applied as I need to. Thanks ! – Celero Apr 13 '11 at 09:04
  • @FelixKling `eval()` can't be used to execute arbitrary code if you take appropriate measures: https://stackoverflow.com/a/53199720/1952991 – ceremcem Nov 08 '18 at 00:08
  • @ceremcem: Fair enough, still seems overkill if there is a simpler and more explicit solution. But hey, everybody can do what they want :) – Felix Kling Nov 08 '18 at 00:19
5

JavaScript: Call Function based on String:

 function foo() { }
 this["foo"]();
Sjoerd
  • 74,049
  • 16
  • 131
  • 175
  • This, basically do the same as eval(), no? – Celero Apr 13 '11 at 08:55
  • 1
    @Celero - no. Run as global code, *this* will reference the gobal/window object so is equivalent to *window['foo']*. If you are using it inside some other scope, you may not have any idea what *this* references. It **does not** reference the scope's variable or activation object (i.e. the execution context), which is what you want as it sits on top of the objects on the variable resolution chain. – RobG Apr 13 '11 at 09:03
3

You can perfectly use eval() without a security risk:

var _cls_ = {}; // serves as a cache, speed up later lookups
function getClass(name){
  if (!_cls_[name]) {
    // cache is not ready, fill it up
    if (name.match(/^[a-zA-Z0-9_]+$/)) {
      // proceed only if the name is a single word string
      _cls_[name] = eval(name);
    } else {
      // arbitrary code is detected 
      throw new Error("Who let the dogs out?");
    }
  }
  return _cls_[name];
}

// Usage
var x = new getClass('Hello')() // throws exception if no 'Hello' class can be found

Pros: You don't have to manually manage a map object.

Cons: None. With a proper regex, no one can run arbitrary code.

ceremcem
  • 3,900
  • 4
  • 28
  • 66
  • How to make this work for a class that is imported e.g. import Grid from '../../mazes/components/Grid' – preston Sep 12 '19 at 03:16
  • If `eval('yourClassName')` returns the object, then it means it's all right. If `eval()` returns `undefined`, then you need to import your class in `getClass()` function's context. – ceremcem Sep 12 '19 at 06:54
-1

Do you mean this?

function Person(name){
    this.name = name;
}

function getClass(str_name, args){
    return new (window[str_name])(args);
}

var wong2 = getClass("Person", "wong2");

alert(wong2.name);   // wong2
wong2
  • 34,358
  • 48
  • 134
  • 179
  • Nope, I've a bunch of class with inheritance among some of them, I only need to load up one of them at a time in a specific case. That's why eval() is just fine for me... – Celero Apr 13 '11 at 08:54
  • I'm sorry, I can't, anyway I'm going to try Felix Kling techniques and see...Thanks for your help – Celero Apr 13 '11 at 09:05