在 JavaScript ECMAScript 6 中从类名创建对象

IT技术 javascript ecmascript-6 es6-class
2021-02-09 14:47:53

我想使用 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');

我做错了什么?

6个回答

不要把类名放在那个对象上。将类本身放在那里,这样您就不必依赖它们是全局的并且可以通过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);
    }
};
实际上很棒的工厂示例,在我的项目中使用了它:)
2021-03-20 14:47:53

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

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

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

let c = createClassByName( 'Person', x, y );
我也是+1。我知道每个人都谴责 eval,但只要您可以完全控制可能的值,它就是最简单、最灵活的解决方案。
2021-03-16 14:47:53
我喜欢这个评估解决方案
2021-04-05 14:47:53
我认为使用 eval() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...存在安全风险
2021-04-09 14:47:53
我喜欢这个 eval,但现在有问题,无法在 es6 类方法中使用 eval 创建变量
2021-04-10 14:47:53

问题是这些类不是 window 对象的属性。您可以使用一个属性“指向”您的类的对象:

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};
显然不在 babeljs 中(不能发布 repl,太长了)
2021-04-06 14:47:53
Column构造不是一个全球性的?
2021-04-09 14:47:53

对于那些不使用 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

我更喜欢这种方法:

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'];