在运行时创建ES6类定义并添加到' factory'要使用的列表

时间:2016-06-29 18:27:42

标签: javascript ecmascript-6 webpack

以下是我目前使用Webpack编译的实现。

// ** ModelTypeA.js ** //
export class ModelTypeA {
  constructor() {
  }
  //etc, class definition
}


// ** ModelFactory.js ** //
export { ModelTypeA } from './ModelTypeA';
export { ModelTypeB } from './ModelTypeB';


// ** Main.js  ** //
import * as ModelFactory from './ModelFactory.js'

let modelName = "ModelTypeA"; //can be changed to "ModelTypeB"
let myModel = new ModelFactory[modelName];

有没有办法创建另一个类,例如ModelTypeC.js及其在运行时的定义(假设我在网页上有一个文本编辑器来编写和保存),将它附加到ModelFactory.js,并在Main.js中使用它?

2 个答案:

答案 0 :(得分:0)

让我们撇开允许用户在您网站上的文本编辑器中编写JS代码的事实通常是一个坏主意。

您无法完成所描述的内容,因为ES6模块不允许对import / export语句进行运行时更改。 This article有一个不错的概述,关键引用:

  

这是基本思路:ES6模块应该是静态可分析的(运行时不能改变导出/导入),因此它不能是动态的。

在这种情况下,你可以做的是以不涉及import / export的某种方式向工厂注册类:

class ModelFactory {
    constructor() {
        this._classes = {}
    }
    register(key, cls) {
        this._classes[key] = cls
    }
    create(key, ...args) {
        return new this._classes[key](...args);
    }
}

// Export a singleton
export default new ModelFactory();

// Register in some other file
import { ModelTypeA } from './ModelTypeA';
import { ModelTypeB } from './ModelTypeB';
import ModelFactory from './ModelFactory';

ModelFactory.register('ModelTypeA', ModelTypeA);
ModelFactory.register('ModelTypeB', ModelTypeB);

现在你可以引入一些用户创作的类并注册它:

const className = userProvidedData.className;
// Again, don't really do this, it's usually a Bad Idea
const cls = eval(userProvidedData.source);
ModelFactory.register(className, cls);

答案 1 :(得分:-2)

在运行时定义一个类(大多数时候)是一个坏主意。 它很容易出现RunTimeException ..

如果这些Model类在公共中有某些东西,那么拥有一个泛型类并根据它具有的属性来改变实例的行为会更好。