You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重写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等概念仍有困惑,想知道代码中遗漏了什么?

问题分析与修正方案

  1. 错误的方法引用方式
    你当前用Array.prototype.methodName是错误的——methodName是变量,不能用点语法访问,必须用方括号[]来动态获取方法,而且不能局限于Array.prototype,方法可能存在于元素自身或者其他原型链上。

  2. 未处理对象类型的集合
    Underscore的_.invoke支持数组和对象两种集合,你的代码只处理了数组,需要补充对象value的遍历逻辑。

  3. 未转发额外参数
    测试用例里要求传递额外参数给目标方法,你需要收集methodName之后的所有参数,再传递给调用的方法。

  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 08:01:31