web-dev-qa-db-fra.com

Créer une instance d'une classe dans ES6 avec un nom dynamique?

Je veux pouvoir instancier une classe ES6 particulière en passant une variable de chaîne à une fonction. Selon la valeur de la variable, une classe différente sera créée.

Exemple - J'ai 2 classes, ClassOne, ClassTwo. Je veux pouvoir passer une variable à une fonction et récupérer une nouvelle classe. Le nom de la classe sera lié à la variable - par exemple. qui passe 'Two' créera ClassTwo.

Je ne pas veux simplement utiliser une clause switch comme ceci:

function createRelevantClass( desiredSubclassName )
{
  let args = [],
      newClass;

  switch( desiredSubclassName )
  {
    case 'One' :
      newClass = new ClassOne(args);
      break;
    case 'Two' :
      newClass = new ClassTwo(args);
      break;
  }

  return newClass;
}

Au lieu de cela, je veux pouvoir créer l'appel du constructeur en utilisant le nom de la variable. Est-ce 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;
}
35
raffjones

Vous pouvez y arriver de plusieurs façons ...

1. Classe de procuration

Suivant l'exemple de @ thefourtheye qui consiste à conserver un mappage de nom en classe, vous pouvez créer une classe dont le travail consiste à prendre le nom de la classe souhaitée et à remplacer son instanciation par celle-ci:

[ Voir ça marche ]

Définissez vos classes

// ClassOne.js
export class ClassOne {
    constructor () {
        console.log("Hi from ClassOne");
    }
}

// ClassTwo.js
export class ClassTwo {
    constructor (msg) {
        console.log(`${msg} from ClassTwo`);
    }
}

Définissez la classe proxy (par exemple, 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;

Exemple d'utilisation

import DynamicClass from './DynamicClass';

new DynamicClass('ClassOne'); //=> "Hi from ClassOne"
new DynamicClass('ClassTwo', 'Bye'); //=> "Bye from ClassTwo"

2. Fonction d'usine

Utilisez une fonction qui effectue une recherche sur un objet de nom de classe -> mappages de classe et renvoie une référence à la classe, que nous pouvons ensuite instancier comme d’habitude.

Définir la fonction d'usine

import ClassOne from './ClassOne';
import ClassTwo from './ClassTwo';

const classes = { ClassOne, ClassTwo };

export default function dynamicClass (name) {
  return classes[name];
}

Exemple d'utilisation

import dynamicClass from './dynamicClass'

const ClassOne = dynamicClass('ClassOne') // Get the ClassOne class

new ClassOne(args) // Create an instance of ClassOne
46
sdgluck

Stockez les classes dans un objet, les clés étant les noms des classes que vous souhaitez qu'elles soient.

const classesMapping = {
  'One': ClassOne,
  'Two': ClassTwo
};

puis créez la classe en fonction du nom de la clé comme ceci

return new classesMapping[desiredSubclassName](args);
20
thefourtheye