如何通过字符串形式的类名在JavaScript中动态创建类实例
JavaScript 通过字符串类名动态创建实例的实现方案
方案1:显式映射表(最推荐)
提前建立字符串标识和类的映射关系,安全性、兼容性最好,不受作用域限制:
class FieldText { constructor() { console.log('hello text field'); } } class FieldTextarea { constructor() { console.log('hello textarea field'); } } // 字符串标识和类的映射表 const fieldClassMap = { text: FieldText, textarea: FieldTextarea } function callField(name) { // 增加合法性校验,避免报错 if (!Reflect.has(fieldClassMap, name)) { throw new Error(`未找到对应类型的字段类:${name}`); } return new fieldClassMap[name](); } callField('text'); // 输出:hello text field callField('textarea'); // 输出:hello textarea field
该方案优势:
- 可控性强,仅允许实例化映射表中提前声明的类,不会出现意外调用
- 兼容性好,无论类定义在全局、ES模块还是CommonJS模块中都可正常使用
- 无安全风险,不会触发任意代码执行
方案2:全局对象获取(仅适用类挂载在全局的场景)
如果你的类是直接定义在全局作用域下的,可以通过全局对象获取类引用:
function callField(name) { // 拼接类名,将传入name的首字母大写 const className = `Field${name.charAt(0).toUpperCase() + name.slice(1)}`; // 浏览器环境用window,Node.js环境替换为globalThis const TargetClass = window[className]; if (!TargetClass) { throw new Error(`未找到全局类:${className}`); } return new TargetClass(); } callField('text'); // 输出:hello text field
该方案注意事项:
- 仅类挂载在全局对象上时生效,模块化场景下类默认不会挂载到全局,该方法会失效
- 存在安全风险,如果传入的name参数不可控,可能实例化到意料之外的全局类,不推荐生产环境使用
注意:虽然使用
eval(new Field${name}())也能实现效果,但eval会执行任意传入的代码,存在极高的代码注入风险,完全不推荐使用。
内容的提问来源于stack exchange,提问作者Jens Törnell
相关产品推荐
相关产品推荐

