在JS中使用Webpack和Babel按名称获取构造函数



我目前正在做一个使用Webpack和Babel的项目。更具体地说,我使用vue-cli框架,但这应该无关紧要。

我想从它的字符串名称中获取构造函数。

我的类就是这样设置在一个世界里的。文件:

export default class World { ... }

在另一个文件中像这样使用:

import World from "./World";

我想做的是:

let foo = new World();
let className = foo.constructor.name;
let bar = new SCOPE[className]();

问题是我没有找到合适的SCOPE。
我试过window[className],它不起作用。
我试过eval('let bar = new ${className}()'),也不工作。
我已经在我的导入下尝试了const SCOPE = (0, eval)("this"),没有更多的成功,它返回window对象。

到目前为止,我找到的唯一解决方案是根据构造函数的名称创建一个映射,但这根本不是动态的。
const classesByName = new Map<string, any>([
[World.name, World],
...
]);

所以…我猜Webpack或Babel在某个地方做了一些事情。
我该怎么办呢?

问题是我没有找到合适的SCOPE

根据你的描述,没有一个。虽然JavaScript引擎会有模块中每个导入的记录,但是你的代码无法访问这个记录列表。

如果你想这样做,你需要把你想要做的对象/构造函数自己放在一个对象或Map中,然后从那里使用它们。

如果>这些不同的构造函数作为模块中的命名导出,如下所示:
export class World { /* ... */ }
export class Universe { /* ... */ }
export class Multiverse { /* ... */ }

…然后,您可以为模块使用模块名称空间对象,如下所示:

import * as constructors from "./your-module.js";
const name = /*...get the name of one of the constructors dynamically...*/;
const newInstance = new constructors[name]();

当然,许多构造函数都希望接收实参。


,,你说:

我想做的是:

let foo = new World();
let className = foo.constructor.name;
let bar = new SCOPE[className]();

如果你有一个类的实例,没有必要这样处理名字,只需要使用foo.constructor:

class World {
}

let foo = new World();
let bar = new foo.constructor();
console.log(bar instanceof World); // true


在你的评论中问:

是否有任何方法可以在任何地方访问我的类定义(没有导出的方式)?至少它对控制台的调试非常有用。

想到的一件事是你可以有一个类注册表,并有你的模块导出类使用注册表。例如:

registry.js:

const registry = new Map();
export function registerClass(cls) {
registry.set(cls.name, cls);
return cls;
}
export function getClass(name) {
return registry.get(name);
}

然后在World.js:

import { registerClass } from "./registry.js";
export default registerClass(class World {
// ...
});

或者如果使用命名导出:

import { registerClass } from "./registry.js";
export class World {
// ...
}
registerClass(World);

当你想使用一个从名称:

import { getClass } from "./registry.js";
const Ctor = getClass(name);
const obj = new Ctor();

最新更新