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

I have a class hierarchy like:

|-> Square AbstractShape -+-> Circle |-> Triangle 

Now I would like to implement a strategy template and create a class object that is stored in a string. In PHP, I would use:

 $type = 'Square'; $obj = new $type(); 

Is there an equivalent in Node.js?

+7
javascript strategy-pattern
source share
4 answers

If you want to go with a more reliable and verifiable approach, you can use a combination of classes and a factory pattern to return an object. Check the following: you will see that with this setting, including more granular logic and testing along the way, it became easier and would provide more flexibility. You also disengage from the new object behind the .issue call, which can be useful and convenient in some cases.

I also notice that you mention your PHP background, so I also demonstrate a little about how the object-oriented approach can be done 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


Also, if you want something more error tolerant than dealing with redundant strings, for example. 'Square' - there are some creative ways to use enumerated approaches that could further refine this. I will save the property here, and not cross out the code snippet, but will include a violin for you to check.

JSFiddle Link - demo demons

+4
source share

A safe way would be to define a factory object:

 function Square() { } // here other constructors for Circle and Triangle var factory = { "Square": Square, "Circle": Circle, "Triangle" : Triangle } var typeName; // here some code which sets typeName var typeObj = new factory[typeName](); 
+4
source share
  • A quick and dirty way is to use eval . But it is strongly discouraged for many reasons: security, performance, readability, support

     function MyType() { } var typeName = 'MyType'; var typeObj = eval('new ' + typeName + '()'); 
  • Much safer and more correct than eval is to use string name matching for types (thanks @GaloisGecko)

     function createType(name) { var types = { "Square": Square, "Circle": Circle, "Triangle": Tringle }; return types.hasOwnProperty(name) ? new types[name]() : null; } 
  • Finally, the best and smartest solution is to use the Factory pattern. See @scniro answer . You can also find a good description and example here.

+2
source share

Upon closer inspection, there is a fairly simple way for Node.js. When you instantiate an object in the simplest way, you actually write new <variableName> , where variableName is the body of some function or class defined and exported in some module. To assign this function / class to a variable, you require() it.

So instead

 const type = 'Square'; const aSquare = new type(); 

you need to write:

 const type = 'Square'; const shape = require(`${pathToShapeModules}/${type}.js`); const aShape = new shape(); 

A minor flaw is that eslint complains (in some rules) that require must be placed on top of the module. And, of course, for the correct handling of exceptions, an attempt is needed ... to catch, etc., Therefore, perhaps the Factory solution is better (therefore, I am going to take it), but I think that for small specialized cases this solution is in order.

+1
source share

All Articles