Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create an instance of a class in ES6 with a dynamic name? [duplicate]

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 create ClassTwo.

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; } 
like image 510
codewithfeeling Avatar asked Jan 07 '16 12:01

codewithfeeling


1 Answers

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 
like image 72
sdgluck Avatar answered Oct 17 '22 23:10

sdgluck