Create an instance of a class in ES6 with a dynamic name?
Solution 1
There are a few ways you can accomplish this...
1. Proxy Class
Following from @thefourtheye's example of maintaining a mapping of name to class, you could have a class whose job is to take the name of the desired class and proxy its instantiation:
[ See it working ]
Define your classes
// ClassOne.js
export class ClassOne {
constructor () {
console.log("Hi from ClassOne");
}
}
// ClassTwo.js
export class ClassTwo {
constructor (msg) {
console.log(`${msg} from ClassTwo`);
}
}
Define the proxy class (e.g. DynamicClass
)
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
// Use ES6 Object Literal Property Value Shorthand to maintain a map
// where the keys share the same names as the classes themselves
const classes = {
ClassOne,
ClassTwo
};
class DynamicClass {
constructor (className, opts) {
return new classes[className](opts);
}
}
export default DynamicClass;
Example usage
import DynamicClass from './DynamicClass';
new DynamicClass('ClassOne'); //=> "Hi from ClassOne"
new DynamicClass('ClassTwo', 'Bye'); //=> "Bye from ClassTwo"
2. Factory Function
Use a function that performs a lookup against an object of class name -> class mappings and returns reference to the class, which we can then instantiate as usual.
Define the factory function
import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';
const classes = { ClassOne, ClassTwo };
export default function dynamicClass (name) {
return classes[name];
}
Example usage
import dynamicClass from './dynamicClass'
const ClassOne = dynamicClass('ClassOne') // Get the ClassOne class
new ClassOne(args) // Create an instance of ClassOne
Solution 2
Store the classes in an Object, with the keys being the names of the classes you want them to be.
const classesMapping = {
'One': ClassOne,
'Two': ClassTwo
};
then create the class based on the key name like this
return new classesMapping[desiredSubclassName](args);
![codewithfeeling](https://i.stack.imgur.com/UWUCW.jpg?s=256&g=1)
codewithfeeling
I'm based in London. I love working with Laravel, React and WordPress, writing solutions for thing that require a bit more than "Advanced Custom Fields" (which I don't use). Being borderline obsessive about detail and finding the most efficient code, I am my own worst enemy in terms of the time I put into my work, but I always want to learn something new on every project, and will never ship anything I'm not proud to show to the world.
Updated on January 20, 2020Comments
-
codewithfeeling over 4 years
I want to be able to instantiate a particular ES6 class by passing a string variable to a function. Depending on the value of the variable, a different class will be created.
Example - I have 2 classes,
ClassOne
,ClassTwo
. I want to be able to pass a variable to a function and get a new class back. The name of the class will be related to the variable - eg. passing'Two'
will createClassTwo
.I don't want to just use a
switch
clause like this:function createRelevantClass( desiredSubclassName ) { let args = [], newClass; switch( desiredSubclassName ) { case 'One' : newClass = new ClassOne(args); break; case 'Two' : newClass = new ClassTwo(args); break; } return newClass; }
Instead, I want to somehow be able to create the constructor call using the variable name. Is that possible?
function createRelevantClass( desiredSubclassName ) { // desiredSubclassName would be string 'One' or 'Two' // how to use the 'new' operator or Reflect here to create the class based on the variable passed in let newClass = ( *magic code to build constructor dynamically* ); return newClass; }