能否通过装饰器实现JS函数内部callFn调用参数的动态修改?
如何动态修改函数内指定
callFn调用的参数? 原代码
let someFunc1 = () => { const name1 = callFn({"k1": "v1", "k2": "v2"}) const name2 = callFn({"k1.1": "v1.1", "k2.1": "v2.1"}) const name3 = callFn({"k1.2": "v1.2", "k2.2": "v2.2"}) } let someFunc2 = () => { const name4 = callFn({"k1": "v1", "k2": "v2"}) const name5 = callFn({"k1.1": "v1.1", "k2.1": "v2.1"}) const name6 = callFn({"k1.2": "v1.2", "k2.2": "v2.2"}) }
需求说明
我想给所有这类someFunc函数添加以下行为:
- 接收一个格式为
{<变量名>: {键: 值}, ...}的对象参数 - 根据参数找到函数内同名变量对应的
callFn调用,修改其传入的参数对象:键存在则更新值,不存在则新增键值对
期望示例
示例1:更新已有键值
调用someFunc1({ "name2": {"k2.1": "myNewValue"} })后,等效于执行:
let someFunc1 = () => { const name1 = callFn({"k1": "v1", "k2": "v2"}) const name2 = callFn({"k1.1": "v1.1", "k2.1": "myNewValue"}) const name3 = callFn({"k1.2": "v1.2", "k2.2": "v2.2"}) }
示例2:新增键值对
调用someFunc2({ "name6": {"myNewKey": "myNewValue"} })后,等效于执行:
let someFunc2 = () => { const name4 = callFn({"k1": "v1", "k2": "v2"}) const name5 = callFn({"k1.1": "v1.1", "k2.1": "v2.1"}) const name6 = callFn({"k1.2": "v1.2", "k2.2": "v2.2", "myNewKey": "myNewValue"}) }
实现方案
直接修改原函数的话,JS没有办法直接获取内部变量和callFn参数的关联关系(函数内部作用域是私有的),所以换个更直观的配置化思路来实现:
步骤1:抽离函数配置
把每个someFunc里的变量名和对应callFn初始参数做成配置对象:
// someFunc1的配置:变量名 -> 初始参数 const someFunc1Config = { name1: {"k1": "v1", "k2": "v2"}, name2: {"k1.1": "v1.1", "k2.1": "v2.1"}, name3: {"k1.2": "v1.2", "k2.2": "v2.2"} }; // someFunc2的配置 const someFunc2Config = { name4: {"k1": "v1", "k2": "v2"}, name5: {"k1.1": "v1.1", "k2.1": "v2.1"}, name6: {"k1.2": "v1.2", "k2.2": "v2.2"} };
步骤2:写生成工具函数
写一个工具函数,接收配置对象,返回可接收修改参数的目标函数:
function createSomeFunc(config) { return function(updates = {}) { // 遍历配置中的每个变量 for (const [varName, originalParams] of Object.entries(config)) { // 合并原参数和更新参数:更新参数优先覆盖原参数 const finalParams = {...originalParams, ...(updates[varName] || {})}; // 执行callFn,和原逻辑一致 callFn(finalParams); } }; }
步骤3:生成目标函数
用工具函数生成我们需要的someFunc1和someFunc2:
const someFunc1 = createSomeFunc(someFunc1Config); const someFunc2 = createSomeFunc(someFunc2Config);
验证调用
现在就可以按照需求调用了:
// 更新name2的k2.1值 someFunc1({ "name2": {"k2.1": "myNewValue"} }); // 给name6新增键值对 someFunc2({ "name6": {"myNewKey": "myNewValue"} });
关于装饰器/反射的说明
- 装饰器目前是JS的Stage 3提案,需要配置Babel或TypeScript才能使用,对新手不友好
- JS的
Reflect反射API无法直接读取函数内部的变量和对应callFn参数,因为函数内部作用域是私有封闭的,外部无法直接访问
上述配置化的方式更直观,容易理解和维护,适合新手快速实现需求。
内容的提问来源于stack exchange,提问作者amy
相关产品推荐
相关产品推荐

