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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34655616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:41:56  来源:igfitidea点击:

Create an instance of a class in ES6 with a dynamic name?

javascriptclassdynamicecmascript-6

提问by raffjones

I want to be able to instantiate a particular ES6 class by passing a string variable to a function. Depending on the value of the variable, a different class will be created.

我希望能够通过将字符串变量传递给函数来实例化特定的 ES6 类。根据变量的值,将创建不同的类。

Example- I have 2 classes, ClassOne, ClassTwo. I want to be able to pass a variable to a function and get a new class back. The name of the class will be related to the variable - eg. passing 'Two'will create ClassTwo.

示例- 我有 2 个类,ClassOne, ClassTwo。我希望能够将变量传递给函数并返回一个新类。类的名称将与变量相关 - 例如。通过'Two'将创建ClassTwo.

I don'twant to just use a switchclause like this:

希望只用一个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;
}

Instead, I want to somehow be able to create the constructor call using the variable name. Is that 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;
}

回答by sdgluck

There are a few ways you can accomplish this...

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

1. Proxy Class

1.代理类

Following from @thefourtheye's example of maintaining a mapping of name to class, you could have a class whose job is to take the name of the desired class and proxy its instantiation:

遵循@thefourtheye 维护名称到类的映射的示例,您可以拥有一个类,其工作是获取所需类的名称并代理其实例化:

[ See it working]

[看到它工作]

Define your classes

定义你的类

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

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

Define the proxy class(e.g. DynamicClass)

定义代理类(例如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;

Example usage

示例用法

import DynamicClass from './DynamicClass';

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

2. Factory Function

2. 工厂​​功能

Use a function that performs a lookup against an object of class name -> class mappings and returns reference to the class, which we can then instantiate as usual.

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

Define the factory function

定义工厂函数

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

const classes = { ClassOne, ClassTwo };

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

Example usage

示例用法

import dynamicClass from './dynamicClass'

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

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

回答by thefourtheye

Store the classes in an Object, with the keys being the names of the classes you want them to be.

将类存储在一个对象中,键是您希望它们成为的类的名称。

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

then create the class based on the key name like this

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

return new classesMapping[desiredSubclassName](args);