javascript - 如何在 JavaScript 中从字符串实例化类

标签 javascript es6-class

我处于一种奇怪的情况,我需要用一个存储在变量中的字符串来实例化一个新类,但即使我确定类名是正确的,我也会收到一个错误,指出给定的类名不是构造函数

这是一个无效的伪代码:

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 对象作为您的查找机制更好,原因如下:

  1. 如果我记得,ES6 中的 class 定义不会像其他顶级变量声明那样自动放在全局对象上(Javascript 试图避免在之前的基础上添加更多垃圾设计错误)。

  2. 因此,如果您要手动分配给查找对象,您最好使用不同的对象,不要污染全局对象。这就是此处使用 dict 对象的原因。

关于javascript - 如何在 JavaScript 中从字符串实例化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49042459/

相关文章:

javascript - 如何从另一个 .js 文件调用一个类?

node.js - 为什么 JetBrains IDE 一直说 Class 和 Constructor 未使用?

javascript - ES6 : Can't Deconstruct inside a call constructor

javascript - 为什么在JavaScript中修改super.method()失败?

javascript - jquery 从 e.target 中删除事件监听器

php - 无法从 Ajax 获取请求取回数据

JavaScript - Highcharts 箱线图不显示

javascript - Internet Explorer 11 上的数组过滤

unit-testing - 如何在 Jest 中测试从构造函数调用然后调用其他异步函数的 init() 函数

javascript - IndexedDB:修改对象存储中预先存在的对象