使用JavaScript中的字符串调用类

时间:2017-07-12 21:05:51

标签: javascript class oop variables

我有多个类似的课程,我想根据情况调用。我有一个变量,它将包含我想要调用的类的名称。

例如,我有这个JavaScript代码定义我的类。

class Parent {
    constructor(id) {
        // Do stuff...
    }
}

class Child1 extends Parent {};

class Child2 extends Parent {}; // and many, many more...

然后我有了这个代码,它创建了一个新的Child1对象。

var obj = new Child1(id);

但是,我希望能够在变量中调用类的名称,然后用它调用它,如下所示:

var className = "Child1"; //Or child 2, depending on scenario.
var obj = new className(id);

我知道在PHP中我可以$obj = new $className(id);,这正是我想用JavaScript做的。

我已经阅读了一些问题的答案(例如this one),表示我可以这样做:

var obj = new window[className](id);

但这样做会返回此错误:

Uncaught TypeError: window[className] is not a constructor

最初我在一个函数中定义了var className = "Child1",我认为问题是className不是全局的,但当我尝试在全局定义className时,它仍然没有工作......

2 个答案:

答案 0 :(得分:1)

class es不会成为全局对象的属性,因此window[...]将不起作用。

您必须构建自己的映射:

// Can also use `Map` instead
const classes = {
  Child1: Child1,
  // or [Child1.name]: Child1 which can be useful if you want to build this dynamically
};

然后通过

查看课程
classes[className]

相关:"Variable" variables in Javascript?

答案 1 :(得分:1)

如果你想让它保持简洁,你需要利用eval的邪恶力量,这样你的代码无论是否被调用都会有效在全球范围内与否:



class ClassA {}
class ClassB {}

const classToInstantiate = 'ClassB';

const myInstance = eval(`new ${classToInstantiate}()`);

console.log(myInstance instanceof ClassB);




虽然不得不诉诸这种技巧,但最终会产生代码异味,如果字符串变量的值以任何方式依赖于用户输入,则可能存在巨大的安全问题。

映射选项是您最有可能想要做的事情,即使它添加了一些样板,它更可靠,您可以更轻松地处理字符串不包含的情况有效的类名,例如:



class ClassA {}
class ClassB {}

const classNamesMap = {
  ClassA,
  ClassB,
};

function getClass(className) {
  if (!className in classNamesMap) {
    console.error('Invalid class name');
    return null;
  }
  return classNamesMap[className];
}

const myInstance = new (getClass('ClassB'))();

console.log(myInstance instanceof ClassB);