Better way to call new constructor classes not using a Switch in Javascript (ES6) [duplicate]

北慕城南 提交于 2020-01-13 07:16:10

问题


I have a class, which depends on type of string, gets in in a swithc statement, and call to de new "class_name" related (constructor).

But, I would like to know if there is a better way to solve this.

It would be ideal if there is a way to call the builder independently, within a specific folder, of all the classes that exist.

Project example:

  • Types/_String.js
  • Types/_Date.js
  • Types/_Integer.js
  • .....
  • TypeSwitcher.js (contains the switch that calls the constructors of the "Types" classes).

Associated Code to "TypeSwitcher.js":

"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";
import Document from "./Inputs/Document";
import Container from "./Inputs/Container";

export default class InputFactory
{
    static getInput(key,typedObject,form,inputDef)
    {
           let type=typedObject.getField(key).getTypeName();
           switch (type) 
           {
             case "String": {
               return new _String(key,typedObject,form,inputDef); 
             } break;

             case "Integer": {
               return new _Integer(key,typedObject,form,inputDef); 
             } break;

             case "Date": {
               return new _Date(key,typedObject,form,inputDef);                
             }break;

             case "Document": {
              return new Document(key,typedObject,form,inputDef);                
            }break;

            case "Container": {
              return new Container(key,typedObject,form,inputDef);                
            }break;  

            default: {throw "Input undefined:"+type}     
           }          
    }       
}

New (edited) I don't have classes only with an underscore "_", also normal. And I have put indent script since I am redefining the basic types of the system to customize them to my need (String.js is reserved and does not leave, so _String.js)

I tried to do something like that:

"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";

const predefinedSystemVar = ["String", "Integer", "Date"];

export default class InputFactory
{
    static getInput (key, typedObject, form, inputDef)
    {
      let type = typedObject.getField(key).getTypeName();
      if (predefinedSystemVar.includes(type) )    
          type = `_${type}`;  
      return eval( `new types[type](key, typedObject, form, inputDef)` );          
    }
}

Updated But it didnot work well, because of webpack. v4 :( I think webpack v4 changes names to imports, etc., and it does not work the code trick ...

Problem, if I create a new class in the future, I would have to add a new "case" and import to contemplate the new constructor.

So, the solution I tried, I dont like so much, because I'd have to add new variables to "predefinedSystemVar"...

Is there something in ES6 or javascript to get this work in a better and optimized way instead of switch -> case?

Additional note: Project enviroment:

  • Webpack v.4.x
  • Babel 7.x
  • ES6

package.json

{
  "devDependencies": {
    "@babel/cli": "^7.7.0",
    "@babel/core": "^7.7.2",
    "@babel/plugin-proposal-class-properties": "^7.7.0",
    "@babel/preset-env": "^7.7.1",
    "babel-loader": "^8.0.6",
    "cypress": "^3.7.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0"
  },

回答1:


Yes, if I am understanding this correctly it should be possible. The below code should work, unless I made some syntactical error. It does require the updating of a classes array, but is less work than updating the switch case and the other solution. I hope this helps and if it does please mark as the answer, have a good rest of your day, cheers!

"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";

const classes = {
    _String,
    _Integer,
    _Date
};

export default class InputFactory
{
    static getInput(key,typedObject,form,inputDef)
    {
           let type=typedObject.getField(key).getTypeName();
           if (classes["_"+type]{
            return new classes["_"+type](key,typedObject,form,inputDef);
           } else {
            throw "Input undefined:"+type
           }         
    }       
}



回答2:


A way is create an object which keys are the same as cases and values are a function that returns a value as you desire as below:

"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";

export default class InputFactory {
    static getInput(key, typedObject, form, inputDef) {
        let type = typedObject.getField(key).getTypeName();
        const operations = {
            "String": () => new _String(key, typedObject, form, inputDef),
            "Integer": () => new _Integer(key, typedObject, form, inputDef),
            "Date": () => new _Date(key, typedObject, form, inputDef),
        }

        try {
            return operations[type]();
        } catch() {
            throw "Input undefined:" + type
        }
    }
}


来源:https://stackoverflow.com/questions/59454558/better-way-to-call-new-constructor-classes-not-using-a-switch-in-javascript-es6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!