17

我想使用 ES6 创建对象工厂,但旧式语法不适用于新语法。

我有下一个代码:

export class Column {}
export class Sequence {}
export class Checkbox {}

export class ColumnFactory {
    constructor() {
        this.specColumn = {
            __default: 'Column',
            __sequence: 'Sequence',
            __checkbox: 'Checkbox'
        };
    }

    create(name) {
        let className = this.specColumn[name] ? this.specColumn[name] : this.specColumn['__default'];
        return new window[className](name); // this line throw error
    }
}

let factory = new ColumnFactory();
let column = factory.create('userName');

我做错了什么?

4

6 回答 6

14

不要把类名放在那个对象上。将类本身放在那里,这样您就不必依赖它们是全局的并且可以通过window.

顺便说一句,没有充分的理由让这个工厂成为一个类,你可能只会实例化一次(单例)。让它成为一个对象:

export class Column {}
export class Sequence {}
export class Checkbox {}

export const columnFactory = {
    specColumn: {
        __default: Column,    // <--
        __sequence: Sequence, // <--
        __checkbox: Checkbox  // <--
    },
    create(name, ...args) {
        let cls = this.specColumn[name] || this.specColumn.__default;
        return new cls(...args);
    }
};
于 2015-08-03T14:31:51.357 回答
10

有一种小而肮脏的方法可以做到这一点:

function createClassByName(name,...a) {
    var c = eval(name);
    return new c(...a);
}

您现在可以创建一个这样的类:

let c = createClassByName( 'Person', x, y );
于 2016-10-16T10:33:53.450 回答
4

问题是类不是窗口对象的属性。您可以拥有一个具有“指向”您的类的属性的对象:

class Column {}
class Sequence {}
class Checkbox {}
let classes = {
  Column,
  Sequence,
  Checkbox 
}

class ColumnFactory {
    constructor() {
        this.specColumn = {
            __default: 'Column',
            __sequence: 'Sequence',
            __checkbox: 'Checkbox'
        };
    }

    create(name) {
        let className = this.specColumn[name] ? this.specColumn[name] : this.specColumn['__default'];
        return new classes[className](name); // this line no longer throw error
    }
}

let factory = new ColumnFactory();
let column = factory.create('userName');

export {ColumnFactory, Column, Sequence, Checkbox};
于 2015-08-02T22:03:26.310 回答
1

对于那些不使用 ES6 并且想知道如何通过使用字符串来创建类的人来说,这是我为使其工作所做的工作。

"use strict";

class Person {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}
window.classes = {};
window.classes.Person = Person;

document.body.innerText = JSON.stringify(new window.classes["Person"](1, 2));

如您所见,最简单的方法是将类添加到对象中。

这是小提琴: https ://jsfiddle.net/zxg7dsng/1/

这是一个使用这种方法的示例项目: https ://github.com/pdxjohnny/dist-rts-client-web

于 2016-01-26T07:03:59.190 回答
1

我更喜欢这种方法:

allThemClasses.js

export class A {}
export class B {}
export class C {}

脚本.js

import * as Classes from './allThemClasses';

const a = new Classes['A'];
const b = new Classes['B'];
const c = new Classes['C'];
于 2017-11-28T22:40:33.687 回答
1

我知道这是一篇旧文章,但最近我对如何动态实例化一个类有同样的问题

我正在使用webpack,所以按照文档,有一种方法可以使用import()函数动态加载模块

js/classes/MyClass.js

class MyClass {
    test = null;
    constructor(param) {
        console.log(param)
        this.test = param;
    }
}

js/app.js

var p = "example";
var className = "MyClass";

import('./classes/'+className).then(function(mod) {
    let myClass = new mod[className](p);
    console.log(myClass);
}, function(failMsg) {
    console.error("Fail to load class"+className);
    console.error(failMsg);
});

当心:这种方法是异步的,我不能真正告诉它的性能成本,但它在我的简单程序上完美运行(值得一试^^)

Ps顺便说一句,我是 Es6 的新手(几天),我更像是 C++ / PHP / Java 开发人员。

我希望这可以帮助遇到这个问题的任何人,这不是一个坏习惯^^”。

于 2020-03-22T16:55:47.923 回答