我处于一种奇怪的情况,我需要使用存储在变量中的字符串来实例化一个新的类,但即使我确定类名是正确的,我得到的错误是给定的类名不是构造函数
这是一个无效的虚拟代码:
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
答案 0 :(得分:2)
一种可能性是使用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
对象在这里的用途。