从类名创建一个新对象,并将该类名作为字符串传递

时间:2019-08-01 06:08:02

标签: javascript typescript class

基于此https://stackoverflow.com/a/46656181/8577819,我创建了一个函数来返回类的对象。

function getInstance<T extends Object>(type: (new (...args: any[]) => T), ...args: any[]): T {
    return new type(...args);
}

class testclass {
    x: string;
    constructor(x:string) {
        this.x=x;
    }
    printcon() {
        console.log("printing from test " + this.x);
    }
}

var dds: testclass = getInstance(testclass,10);
dds.printcon();

/// Console prints 
// printing from test 10

是否可以将类名称本身作为字符串参数传递给对象创建者?

clnm: string = "testclass";
var dds2: <clnm> = getInstance(clnm,10);
dds2.printcon();

3 个答案:

答案 0 :(得分:2)

我通过使用以下类似的代码完成了相同的任务:

假设我们必须创建Instance文件夹下的modules类。

modules/Calulator.ts在构造函数中也采用了一个参数:

export class Calculator {

    c: number;

    constructor(cc: number) {
        this.c = cc;
    }
    sum(a: number, b: number): number {
        return a + b + Number(this.c);
    }
}

我们的InstanceBuilder类不使用eval(也使用eval的注释工作代码):

import * as wfModule from "../modules";
export class InstanceBuilder {

    getInstance(className: string, ...args: any[]): any {

        // TODO: Handle Null and invalid className arguments
        const mod: any = wfModule;
        if (typeof mod[className] !== undefined) {
            return new mod[className](args);
        } else {
            throw new Error("Class not found: " + className);
        }

        // Other working methods:
        // const proxy: any = undefined;
        // const getInstance = (m) => eval("obj = Object.create(m." + className + ".prototype);");
        // eval("obj = new mod['" + className + "'](" + args + ")");
        // eval("proxy.prototype = Object.create(mod." + className + ".prototype);");
        // obj.constructor.apply(args);
    }
}

然后,要动态创建类,可以执行以下操作:

const instanceBuilder = new InstanceBuilder();
const commandInstance = instanceBuilder.getInstance("Calculator", initArgsValues);

上述解决方案应该可以使用(但不能在所有用例中进行测试,但是应该可以帮助您入门。)

答案 1 :(得分:1)

我建议创建可能选项的地图:

const availableClasses = {
    testclass: testclass,
    anyOtherName: SomeClass
};

function getInstanceByName(name, ...args) {
    const Class = availableClasses[name];
    return getInstance(Class, ...args);
}

// Usage:
// getInstanceByName('testclass', 10)
// getInstanceByName('anyOtherName', 10)

如果您真的想使用动态调用,出于安全方面的考虑,我不推荐这样做,但是您可以使用:

function getInstanceByName(name, ...args) {
    const Class = eval(name);
    return getInstance(Class, ...args);
}

// Usage:
// getInstanceByName('testclass', 10)

// But it is not safe, as you may exploit it as well:
// getInstanceByName('function () { alert("abc"); }')

答案 2 :(得分:0)

您不必手动发送名称。您可以使用constructor属性

获取类名。

class testclass {
  x;
  constructor(x) {
    this.x = x;
  }
  printcon() {
    console.log("printing from test " + this.x);
  }
}

const instance = new testclass(10)
instance.printcon()

// name of the constructor or class it was created from
console.log(instance.constructor.name)