JavaScript如何将类/对象方法暴露给运行时字符串生成的脚本调用
核心问题分析
Function构造函数参数使用错误:Function要求参数名以独立字符串的形式依次传入,你直接传入scope数组会被隐式转为单个逗号拼接的字符串作为唯一参数名,导致传入的三个值无法对应到三个独立变量,脚本内访问randomIntFromInterval会报未定义错误。- getter提前执行问题:遍历
config取值时就会触发randomIntFromInterval的getter执行,当前逻辑下虽然返回绑定后的函数不会直接报错,但如果getter包含依赖执行时机的逻辑,会出现预期外的行为。 - 如果后续要暴露类的实例方法,
Object.keys无法遍历到原型链上的方法,会出现方法遗漏的问题。
修复方案
方案1:最小改动适配现有逻辑
仅修改NamedFunction中构造Function的部分,将scope数组展开为独立参数传入即可:
export function NamedFunction(name, args, body, scope, values) { if (typeof args == 'string') { values = scope; scope = body; body = args; args = []; } if (!Array.isArray(scope) || !Array.isArray(values)) { if (typeof scope == 'object') { var keys = Object.keys(scope); values = keys.map(function (p) { return scope[p]; }); scope = keys; } else { values = []; scope = []; } } // 核心改动:将scope数组展开为独立参数传入Function构造函数 return Function(...scope, 'function ' + name + '(' + args.join(', ') + ') {\n' + body + '\n}\nreturn ' + name + ';' ).apply(null, values); }
修改后你的现有代码即可正常运行,randomIntFromInterval可以正常调用。
方案2:更稳定的上下文暴露方案(推荐用于类方法场景)
如果后续需要暴露类的内部方法,更建议直接把类实例/配置对象作为单个上下文变量暴露给脚本,避免属性遍历遗漏、getter提前执行、变量名冲突等问题:
export const executeFns = () => { // 脚本内通过ctx访问所有暴露的属性和方法 let edit = ` let a = ctx.randomIntFromInterval(); let b = ctx.randomIntFromInterval(); if (a> b) { console.log('a is bigger than b') } else if (b>a) { console.log('b is bigger than a') } console.log('a',a ); console.log('b',b )`; var f4 = NamedFunction('fancyname', [], edit, {ctx: config}); f4(); };
注意:动态执行字符串脚本存在安全风险,请确保所有待执行的脚本均为可信来源,避免代码注入攻击。
内容的提问来源于stack exchange,提问作者Rahul Joshi
相关产品推荐
相关产品推荐

