gpt4 book ai didi

javascript - 如何将字符串或类传递给方法以创建实例

转载 作者:搜寻专家 更新时间:2023-10-30 21:24:27 26 4
gpt4 key购买 nike

我将使用以下方法,它通过向它传递一个类型来工作,例如 obj.addComponent(MyClass)。这很好用。

我试图通过添加 | 来修改 type 参数string 给它,但它现在给我错误说:

Cannot use 'new' with an expression whose type lacks a call or construct signature.

我是否可以修改它以便我可以传递类名或类的字符串版本?

这是我有但不起作用的:

public addComponent<T extends Component>(type: ComponentType<T> | string): T {
let comp;
comp = new type() as T;
comp.name = comp.constructor.name;
}

这是它的依赖项:

class Component extends Obj {

}

interface ComponentType<T extends Component> {
new(): T;
}

我已经尝试使用 Object.create(),它工作正常,但后来我得到一个新的错误:

Uncaught TypeError: Cannot assign to read only property 'name' of object '[object Object]'

编辑:

最后,我希望能够将以下内容传递给 addComponent:

obj.addComponent(MyClass);

或者

obj.addComponent("MyClass");

最佳答案

在 javascript 中无法使用名称获取类,它没有类似于 java ClassLoader 的东西。
您可以通过创建自己的机制来解决这个问题,可能有很多方法可以做到这一点,但这里有 3 个选项。

(1) 为您的组件类维护一个注册表:

const REGISTRY: { [name: string]: ComponentType<Component> } = {};

class Component {}

class MyComponent1 extends Component {}
REGISTRY["MyComponent1"] = MyComponent1;

class MyComponent2 extends Component {}
REGISTRY["MyComponent2"] = MyComponent2;

type ComponentType<T extends Component> = {
new(): T;
}

function factory<T extends Component>(type: ComponentType<T> | string): T {
return typeof type === "string" ?
new REGISTRY[type]() as T:
new type();
}

( code in playground )

如果您采用这种方法,那么我建议让 REGISTRY 成为一个包含集合的对象,这样您就可以只添加构造函数并从中获取名称。

这个有一个变体,那就是使用装饰器:

function register(constructor: typeof Component) {
REGISTRY[(constructor as any).name] = constructor;
}

@register
class MyComponent1 extends Component {}

@register
class MyComponent2 extends Component {}

( code in playground )

(2) 将组件包装在命名空间中(正如@Shilly 在评论中建议的那样):

namespace components {
export class Component {}
export class MyComponent1 extends Component {}
export class MyComponent2 extends Component {}

export type ComponentType<T extends Component> = {
new(): T;
}

export function forName(name: string): ComponentType<Component> {
if (this[name] && this[name].prototype instanceof Component) {
return this[name];
}
}
}

function factory<T extends components.Component>(type: components.ComponentType<T> | string): T {
return typeof type === "string" ?
new (components.forName(type))() as T:
new type();
}

( code in playground )

如果您要使用这种方法,那么您需要确保导出所有组件类。

(3) 使用eval

class Component {}
class MyComponent1 extends Component {}
class MyComponent2 extends Component {}

type ComponentType<T extends Component> = {
new(): T;
}

function factory<T extends Component>(type: ComponentType<T> | string): T {
return typeof type === "string" ?
new (eval(type))() as T:
new type();
}

( code in playground )

这不是推荐的方法,您可以 read all about the cons在很多地方使用 eval
但它仍然是一个选项,所以我将其列出。

关于javascript - 如何将字符串或类传递给方法以创建实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39105390/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com