我处于一种奇怪的情况,我需要用一个存储在变量中的字符串来实例化一个新类,但即使我确定类名是正确的,我也会收到一个错误,指出给定的类名不是构造函数
这是一个无效的伪代码:
class Foo {
constructor(){
console.log('Foo!');
}
};
const foo = 'Foo';
const bar = new window[foo]();
console.log(bar);
这个错误:
Uncaught TypeError: window[foo] is not a constructor
最佳答案
一种可能是使用eval
。
class Foo {
constructor() {
console.log('Foo!');
}
};
const foo = 'Foo';
const bar = eval(`new ${foo}()`);
console.log(bar);
您必须评估在您的特定情况下使用 eval()
的安全性。如果您知道要插入到运行 eval()
的代码中的字符串的来源,或者您可以先对其进行清理,那么它可能是安全的。
我个人更喜欢查找表。如果您有已知数量的要按字符串映射的类,那么您可以制作自己的查找表并使用它。这样做的好处是,如果字符串中有奇怪的东西,就不会产生意想不到的后果:
class Foo {
constructor() {
console.log('Foo!');
}
};
class Goo {
constructor() {
console.log('Goo!');
}
};
// construct dict object that contains our mapping between strings and classes
const dict = new Map([
['Foo', Foo],
['Goo', Goo]
]);
// make a class from a string
const foo = 'Foo';
let bar = new(dict.get(foo))()
console.log(bar);
如果你真的打算走这条路,你可能想把它封装在一个函数中,然后在 dict
中找不到该字符串时添加错误处理。
这应该比使用全局或 Window
对象作为您的查找机制更好,原因如下:
如果我记得,ES6 中的
class
定义不会像其他顶级变量声明那样自动放在全局对象上(Javascript 试图避免在之前的基础上添加更多垃圾设计错误)。因此,如果您要手动分配给查找对象,您最好使用不同的对象,不要污染全局对象。这就是此处使用
dict
对象的原因。
关于javascript - 如何在 JavaScript 中从字符串实例化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49042459/