重写Underscore库_.invoke函数遇参数传递问题,求技术帮助
重写Underscore的
_.invoke函数问题解析 我是一名初学者,正在尝试重写Underscore库的_.invoke函数。该函数需要返回一个数组,包含集合中每个值调用指定方法后的结果。
我的代码:
_.invoke = function(collection, methodName) { var result = []; if (Array.isArray(collection)) { for (let i = 0; i < collection.length; i++) { methodName.call(collection[i]) var value = collection[i][methodName] result.push(value) } } return result }
问题分析:
我觉得问题出在methodName.call(collection[i])这一行——我想在collection[i]对象上调用该方法,同时传递单元测试里可能有的参数。之前试过用typeof(methodName) === "function"判断方法是否为函数,但还是没解决问题。
问题根源及修正方案
你的代码有几个核心问题:
- 调用方法后没捕获返回值:你调用
methodName.call后,反而把方法本身(collection[i][methodName])push进数组,完全搞反了逻辑; - 未处理方法名字符串的情况:比如传入
'toUpperCase'这种方法名时,你的代码会把它当成函数去调用,直接报错; - 不支持额外参数传递:没法把单元测试里的参数传给目标方法;
- 只支持数组集合:对象类型的集合完全没处理。
修正后的代码
_.invoke = function(collection, methodName) { const result = []; // 统一处理集合:数组直接用,对象转成值数组 const values = Array.isArray(collection) ? collection : Object.values(collection); // 获取调用时传入的额外参数(除了collection和methodName之外的参数) const args = Array.prototype.slice.call(arguments, 2); for (let i = 0; i < values.length; i++) { const currentItem = values[i]; let targetMethod; // 区分传入的是方法名字符串还是函数本身 if (typeof methodName === 'string') { targetMethod = currentItem[methodName]; } else if (typeof methodName === 'function') { targetMethod = methodName; } // 确保方法存在且可调用,执行后收集结果 if (typeof targetMethod === 'function') { const callResult = targetMethod.apply(currentItem, args); result.push(callResult); } else { // 方法不存在时,按需求返回undefined(也可以根据情况调整) result.push(undefined); } } return result; };
关键细节说明
- 集合兼容:用
Object.values把对象转换成值数组,确保数组和对象类型的集合都能被遍历; - 参数传递:通过
arguments.slice(2)提取额外参数,用apply方法把参数数组传给目标方法,适配任意数量的参数; - 方法类型兼容:既支持传入方法名字符串(比如
'slice'),也支持传入函数本身(比如Array.prototype.slice); - 结果收集:捕获方法调用的返回值,正确push进结果数组,而不是方法本身。
内容的提问来源于stack exchange,提问作者OWELEY
相关产品推荐
相关产品推荐

