Crear objeto a partir del nombre de la clase en JavasScript ECMAScript 6

Resuelto Serhii Popov asked hace 9 años • 9 respuestas

Quiero crear una fábrica de objetos usando ES6 pero la sintaxis antigua no funciona con la nueva.

Tengo el siguiente código:

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

¿Qué hago mal?

Serhii Popov avatar Aug 03 '15 04:08 Serhii Popov
Aceptado

No pongas nombres de clases en ese objeto. Coloque las clases allí, para que no tenga que depender de que sean globales y accesibles (en los navegadores) a través de window.

Por cierto, no hay una buena razón para hacer de esta fábrica una clase, probablemente solo crearías una instancia de ella una vez (singleton). Simplemente conviértalo en un objeto:

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);
    }
};
Bergi avatar Aug 03 '2015 14:08 Bergi

Hay una forma pequeña y sucia de hacerlo:

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

Ahora puedes crear una clase como esa:

let c = createClassByName( 'Person', x, y );
eco747 avatar Oct 16 '2016 10:10 eco747

El problema es que las clases no son propiedades del objeto ventana. En su lugar, puedes tener un objeto con propiedades "apuntando" a tus clases:

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};
Amit avatar Aug 02 '2015 22:08 Amit