重写Underscore _.invoke方法遇阻,请求技术解析
重写Underscore _.invoke方法遇到的问题
我正在学习重写Underscore的_.invoke方法,当前代码如下:
_.invoke = function (collection, methodName) { let result = []; // debugger; if (Array.isArray(collection)) { // 检查collection是否为数组 for (let i = 0; i < collection.length; i++) { // 遍历collection result.push(Array.prototype.methodName.call(collection[i])); } } console.log('result:', result); return result; };
遇到的问题
调试时执行到call就跳出循环,测试报错:
_.invoke(mocks.arr, 'testCall').should.eql(mocks.arr); _.invoke(mocks.obj, 'testCall').should.eql(mocks.objValuesArr);
还有参数相关测试不通过:
argsArr = [mocks.arr, mocks.obj]; _.invoke(mocks.arr, 'testArgs', mocks.arr, mocks.obj); called.should.be.true; called = false; argsArr = [mocks.obj, mocks.arr]; _.invoke(mocks.obj, 'testArgs', mocks.obj, mocks.arr); called.should.be.true;
我的疑问
- 不清楚传入
methodName的具体方法是什么,不确定是否需要转发额外参数(比如类似.reduce这类需要参数的方法) - 对
this、thisArg等概念仍有困惑,想知道代码中遗漏了什么?
问题分析与修正方案
错误的方法引用方式
你当前用Array.prototype.methodName是错误的——methodName是变量,不能用点语法访问,必须用方括号[]来动态获取方法,而且不能局限于Array.prototype,方法可能存在于元素自身或者其他原型链上。未处理对象类型的集合
Underscore的_.invoke支持数组和对象两种集合,你的代码只处理了数组,需要补充对象value的遍历逻辑。未转发额外参数
测试用例里要求传递额外参数给目标方法,你需要收集methodName之后的所有参数,再传递给调用的方法。this绑定逻辑
调用方法时,this必须指向当前遍历的元素(数组项或对象value),这样方法内部的this才能正确指向目标元素。
修正后的代码示例:
_.invoke = function (collection, methodName) { const result = []; // 收集methodName之后的所有额外参数 const args = Array.prototype.slice.call(arguments, 2); // 统一处理数组和对象:转为可遍历的items数组 const items = Array.isArray(collection) ? collection : Object.values(collection); for (const item of items) { // 获取目标方法:如果methodName是函数则直接用,否则从item上取对应方法 const targetMethod = typeof methodName === 'function' ? methodName : item[methodName]; if (targetMethod) { // 绑定this为当前item,传递额外参数并收集结果 result.push(targetMethod.apply(item, args)); } else { // 没有找到方法时按Underscore逻辑返回undefined result.push(undefined); } } return result; };
关键知识点说明
- 动态获取方法:用
item[methodName]替代硬编码的原型访问,适配不同元素的方法位置。 - 参数转发:通过
arguments收集额外参数,用apply(或ES6扩展运算符+call)传递给目标方法。 - 多集合类型支持:用
Object.values把对象转为value数组,统一遍历逻辑。 - this绑定:
apply的第一个参数就是方法执行时的this,确保方法内部能访问到当前遍历的元素。
内容的提问来源于stack exchange,提问作者dr3nan
相关产品推荐
相关产品推荐

