ES6 Modules下如何实现类似window[函数名字符串]的动态调用效果
ES6模块动态调用导出方法的解决方案
ES模块通过import * as 别名导入的对象本身就是普通的可枚举对象,完全支持方括号动态属性访问,不需要挂载到全局window上就能实现和之前全局动态调用一样的效果,以下是三种常用实现方案:
方案1:直接通过模块对象访问(最简便)
如果你的方法名字符串仅保存方法名本身,不需要带模块前缀,直接用模块对象做动态属性访问即可,逻辑和你之前用window[nextMethodName]()完全一致:
// 定义要调用的方法名 let nextMethodName = "aFunctionName"; // 调用前先做类型校验,避免方法不存在时抛出错误 if (typeof myModule[nextMethodName] === 'function') { // 无参数调用 myModule[nextMethodName](); // 需要传参直接在括号内加参数即可:myModule[nextMethodName](param1, param2) }
方案2:支持带模块前缀的方法名字符串
如果你需要使用"myModule.aFunctionName"这类带模块前缀的字符串作为调用标识,可以拆分字符串后结合模块映射表实现:
let nextMethodName = "myModule.aFunctionName"; // 拆分得到模块别名和方法名 const [moduleAlias, methodName] = nextMethodName.split('.'); // 提前维护所有支持动态调用的模块映射表 const moduleMap = { myModule: myModule, // 后续有其他模块需要支持可直接在此处扩展 }; // 校验后调用 if (moduleMap[moduleAlias] && typeof moduleMap[moduleAlias][methodName] === 'function') { moduleMap[moduleAlias][methodName](); }
方案3:显式维护允许调用的方法映射表(推荐)
如果不想开放模块所有导出方法给动态调用,建议单独维护白名单映射表,安全性最高:
// 提前定义允许动态调用的方法集合,仅在列表内的方法可被触发 const allowedMethodMap = { aFunctionName: myModule.aFunctionName, otherAllowedMethod: myModule.otherPublicMethod, // 其他允许调用的方法可在此扩展 }; let nextMethodName = "aFunctionName"; if (typeof allowedMethodMap[nextMethodName] === 'function') { allowedMethodMap[nextMethodName](); }
注意事项
如果调用的方法内部依赖this指向模块对象,可使用call/apply/bind手动绑定执行上下文,例如:
myModule[nextMethodName].call(myModule, param1, param2)
内容的提问来源于stack exchange,提问作者Andromeda
相关产品推荐
相关产品推荐

