【问题标题】:Dynamically choose class from string - "MyClassName" -> MyClassName [duplicate]从字符串中动态选择类-“MyClassName”-> MyClassName [重复]
【发布时间】:2015-12-28 06:17:26
【问题描述】:

我使用 babel.js traspiler 编写 ES6 代码。

我有一个包含类名的字符串。我想要一个可以实例化的类。怎么样?

我试过了:

eval("MyClassName") -> :(
window["MyClassName"] -> :(

有什么想法吗?

【问题讨论】:

  • 你在 Babel 中使用什么模块系统?默认情况下它是普通的 JS,所以任何 on this page 都可以工作。
  • 你能详细说明你为什么要这样做吗?根据用例,可能会有一些选择,但总的来说,正如您所见,答案是否定的,没有eval
  • 你能提前把你想用的类塞进一个对象中吗?你想用某个模块的命名导出来做这个类吗?
  • 其实eval 只要类在范围内就可以工作。
  • 支持-> :( :)))

标签: javascript ecmascript-6 babeljs


【解决方案1】:

您可以:

由于使用 BabelJS,您必须转译为 ES5 模块加载器,因此它很简单(取决于您在转译时指定的 module format):

const MyClassName = require("MyClassName");
const obj = new MyClassName();

然而,这不是 ES6,而是转译的 ES5。所以你的代码不会在真正的 ES6 环境中工作。

在 ES6 环境中,class 只是函数的语法糖,所以你没有理由不能这样做:

// Class definition
class MyClassName { }
// Pollute global scope
(global || window).MyClassName = MyClassName;

然后像这样加载它:

const instance = new (window || global)["MyClassName"]();

但是这样做你只是破坏了最初提供给你的主要功能模块。

你应该:

创建一个工厂类。在大多数情况下,您可以实例化的类的数量是有限的。您应该创建一个工厂函数,它为您提供基于字符串的类实例:

import MyClassName from "./MyClassName"
class MyFactory {
    static getInstance(value) {
        if(value === "MyClassName") {
            return new MyClassName();
        }
        throw new Error(`Could not instantiate ${value}`);
    }
}

将用作:

import MyFactory from "./MyFactory";
const instance = MyFactory.getInstance("MyClassName");

显然,您可以扩展它以使用 Map 而不是一串 if 语句,但您明白了。

【讨论】:

  • 谢谢!非常周到的回应。我只是用谷歌搜索了同样的东西,我发现了这个线程(经典),然后才意识到我没有看到你的通知。我正在查看我不喜欢的同一段代码。这就是你在“你应该”中描述的。好吧,我会继续添加到工厂类中。
  • 工厂应该是类有什么原因吗?我不能只使用工厂函数吗?
  • 完全没有理由。回顾这个答案,我现在不会在这里选择类语法。常规函数也可以。
猜你喜欢
  • 2014-08-09
  • 2012-07-08
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-09
  • 1970-01-01
相关资源
最近更新 更多