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 {}
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'];
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 );
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 know this is an old post, but recently I've had the same question about how to instance a class dynamically
I'm using webpack so following the documentation there is a way to load a module dynamically using the import() function
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);
});
Beware: this method is asynchronous and I can't really tell the performance cost for it, But it works perfectly on my simple program (worth a try ^^)
Ps: To be fare I'm new to Es6 (a couple of days) I'm more a C++ / PHP / Java developer.
I hope this helps anyone that come across this question and that is it not a bad practice ^^".
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};