Создать экземпляр класса в ES6 с динамическим именем?

Я хочу иметь возможность создать экземпляр определенного класса ES6, передав строковую переменную функции. В зависимости от значения переменной будет создан другой класс.

Пример. У меня есть 2 класса, ClassOne, ClassTwo. Я хочу иметь возможность передать переменную функции и вернуть новый класс. Имя класса будет связано с переменной - например. прохождение 'Two' создаст ClassTwo.

Я не хочу просто использовать предложение switch следующим образом:

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

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

  return newClass;
}

Вместо этого я хочу как-то создать вызов конструктора, используя имя переменной. Возможно ли это?

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;
}

Ответы

Ответ 1

Есть несколько способов сделать это...

1. Прокси-класс

Следуя примеру @thefourtheye сохранения сопоставления имени в класс, у вас может быть класс, задачей которого является присвоение имени желаемого класса и прокси-сервера его экземпляру:

[Посмотрите, как работает.

Определите свои классы

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

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

Определить класс прокси (например, 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;

Использование примера

import DynamicClass from './DynamicClass';

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

2. Factory Функция

Используйте функцию, которая выполняет поиск по объекту класса name → сопоставления классов и возвращает ссылку на класс, который мы можем затем создать как обычно.

Определить функцию Factory

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

const classes = { ClassOne, ClassTwo };

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

Использование примера

import dynamicClass from './dynamicClass'

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

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

Ответ 2

Храните классы в объекте, с ключами, которые являются именами классов, которые вы хотите, чтобы они были.

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

затем создайте класс на основе имени ключа, подобного этому

return new classesMapping[desiredSubclassName](args);