Crear objeto a partir del nombre de la clase en JavasScript ECMAScript 6
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?
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);
}
};
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 );
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};