I want create object factory using ES6 but old-style syntax doesn\'t work with new.
I have next code:
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\');
What do I do wrong?
Don\'t put class names on that object. Put the classes themselves there, so that you don\'t have to rely on them being global and accessible (in browsers) through window
.
Btw, there\'s no good reason to make this factory a class, you would probably only instantiate it once (singleton). Just make it an object:
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);
}
};
There is a small & dirty way to do that:
function createClassByName(name,...a) {
var c = eval(name);
return new c(...a);
}
You can now create a class like that:
let c = createClassByName( \'Person\', x, y );
The problem is that the classes are not properties of the window object. You can have an object with properties \"pointing\" to your classes instead:
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};
For those of you that are not using ES6 and want to know how you can create classes by using a string here is what I have done to get this to work.
\"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));
As you can see the easiest way to do this is to add the class to an object.
Here is the fiddle:
https://jsfiddle.net/zxg7dsng/1/
Here is an example project that uses this approach:
https://github.com/pdxjohnny/dist-rts-client-web
I prefer this method:
allThemClasses.js
export class A {}
export class B {}
export class C {}
script.js
import * as Classes from \'./allThemClasses\';
const a = new Classes[\'A\'];
const b = new Classes[\'B\'];
const c = new Classes[\'C\'];