我目前正在做一个使用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在某个地方做了一些事情。
我该怎么办呢?
根据你的描述,没有一个。虽然JavaScript引擎会有模块中每个导入的记录,但是你的代码无法访问这个记录列表。问题是我没有找到合适的SCOPE
如果你想这样做,你需要把你想要做的对象/构造函数自己放在一个对象或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();