使用动态名称在ES6中创建类的实例?

raf*_*nes 39 javascript class dynamic ecmascript-6

我希望能够通过将字符串变量传递给函数来实例化特定的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;
}
Run Code Online (Sandbox Code Playgroud)

相反,我想以某种方式能够使用变量名创建构造函数调用.那可能吗?

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;
}
Run Code Online (Sandbox Code Playgroud)

sdg*_*uck 50

有几种方法可以实现这一目标......

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`);
    }
}
Run Code Online (Sandbox Code Playgroud)

定义代理类(例如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;
Run Code Online (Sandbox Code Playgroud)

用法示例

import DynamicClass from './DynamicClass';

new DynamicClass('ClassOne'); //=> "Hi from ClassOne"
new DynamicClass('ClassTwo', 'Bye'); //=> "Bye from ClassTwo"
Run Code Online (Sandbox Code Playgroud)

2.工厂功能

使用一个函数对类名对象 - >类映射执行查找,并返回对类的引用,然后我们可以像往常一样实例化.

定义工厂功能

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

const classes = { ClassOne, ClassTwo };

export default function dynamicClass (name) {
  return classes[name];
}
Run Code Online (Sandbox Code Playgroud)

用法示例

import dynamicClass from './dynamicClass'

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

new ClassOne(args) // Create an instance of ClassOne
Run Code Online (Sandbox Code Playgroud)

  • 它实际上不一定是一个类.它可以是一个简单的工厂功能.一个类有点矫枉过正恕我直言. (8认同)
  • 我不同意这种做法。返回值不应该是一个类,而应该是从工厂请求的类的对象。请查看以下链接:https://en.wikipedia.org/wiki/Factory_method_pattern (2认同)
  • 如果您有一个包含许多类的库,并且类的数量和名称不时发生变化,那么这不是很方便。每次更新时,您都必须将新类的名称添加到代理中。 (2认同)

the*_*eye 22

将类存储在Object中,键是您希望它们成为的类的名称.

const classesMapping = {
  'One': ClassOne,
  'Two': ClassTwo
};
Run Code Online (Sandbox Code Playgroud)

然后根据这样的键名创建类

return new classesMapping[desiredSubclassName](args);
Run Code Online (Sandbox Code Playgroud)

  • @RGraham 不。不必要。 (2认同)
  • 大开眼界..谢谢!但是如果desiredSubclassName 实际上已经与类名相同怎么办?将“ClassOne”映射到 ClassOne 对我来说似乎有点多余。我很感激任何建议。 (2认同)