How to Make JavaScript Object Using a Variable String to Define the Class Name

How do I make JavaScript Object using a variable String to define the class name?

Would it work if you did something like this:

var myObject = window[classNameString];

..?

How to instantiate a Class from a String in JavaScript

One possibility is to use eval.

class Foo {
constructor() {
console.log('Foo!');
}
};
const foo = 'Foo';
const bar = eval(`new ${foo}()`);
console.log(bar);

Create Class Definition from String

One way to achieve this is to add the text that instantiates the class to the string and only then eval it:

const def = 'class M {}';
const instantiator = def + '; new M();';

const m = eval(instantiator);

EDIT:

To follow-up on the comment, if you want the class itself, it's even simpler - just add its name to the string you're evaluating:

const def = 'class M {}';
const statement = def + '; M;';

const M = eval(statement);
const m = new M(); // This now works!

Node.js - create object of class name specified in variable

If you're wishing to go with a more robust and testable approach, you could use a combination of classes and a factory pattern to issue the object. Check out the following, you'll see that with this setup, including more granular logic and testing down the road would come easier and afford you greater flexibility. You're also abstracting away new-ing up the object yourself behind the .issue call - which can be beneficial and convenient in some cases.

I also notice that you mention your PHP background, so I'm also showcasing a bit of how an object orientated approach can be taken in ES6.

class AbstractShape {
constructor(type) {
this.type = type;
}

getType() {
console.log(`I am a ${this.type}`);
}
}

class Square extends AbstractShape {
constructor(type) {
super(type);
this.sides = 4;
}

getDescription() {
console.log(`I have ${this.sides} equal sides`);
}
}

class ShapeFactory {
static issue(type) {
switch(type) {
case 'Square': return new Square(type);
break;
case 'Circle': /* same pattern with a Circle class */
break;
}
}
}

let shape = ShapeFactory.issue('Square');

shape.getType(); /* I am a Square */
shape.getDescription(); /* I have 4 equal sides */

JSFiddle Link - demo


Furthermore, if you'd like something a bit more fault tolerant than dealing with redundant strings e.g. 'Square' - there are some creative ways to leverage enum-like approaches that could refine this even further. I'll save the real estate here and not re-hash the code snippet, but will include a fiddle for you to check out.

JSFiddle Link - enum approach demo

ES6 class instance from string

Only global variables are put into window automatically.

Create an object that maps from class names to classes:

const classMap = {
"MyClass": MyClass,
"MyClass2": MyClass2,
...
};

Then use classMap[name](params) rather than window[name](params).

Call a class with a string in JavaScript

If you want to keep it as concise as you'd want, this is a case where you need to harness the evil powers of eval, so that your code works whether it's invoked in the global scope or not:

class ClassA {}class ClassB {}
const classToInstantiate = 'ClassB';
const myInstance = eval(`new ${classToInstantiate}()`);
console.log(myInstance instanceof ClassB);

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

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


Related Topics



Leave a reply



Submit