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

实现Underscore库invoke方法遇异常,求原理性提示

Underscore简化版invoke方法实现疑问

已实现的简化版each方法(通过所有测试)

_.each = function (collection, iteratee, context) {
  let keys = Object.keys(collection);
  if (Array.isArray(collection)) {
    for (let i=0; i<keys.length; i++) {
      iteratee.call(context, collection[keys[i]], i, collection);
    }
  }
  else {
    for (let i=0; i<keys.length; i++) {
      iteratee.call(context, collection[keys[i]], keys[i], collection);
    }
  }
  return collection;
};

invoke方法需求说明

// _.invoke(collection, methodName, *arguments)
// Returns an array with the results of calling the method indicated by methodName on each value in the collection.
// Any extra arguments passed to invoke will be forwarded on to the method invocation.

三次实现尝试及问题

尝试1:parseInt正常工作,但join报错

function invoke1 (collection, methodName) {
  let resArray = [];
  _.each(collection, el => resArray.push(methodName(el)));
  return resArray;
}

console.log(invoke1(['1','2','3'], parseInt)); // [123]
console.log(invoke1([['a','b','c'], ['d','e','f']], Array.prototype.join)); // Uncaught TypeError: Cannot convert undefined or null to object - expected ['a,b,c', 'd,e,f']

尝试2:join正常工作,但parseInt返回NaN

function invoke2 (collection, methodName) {
  let resArray = [];
  _.each(collection, el => resArray.push(methodName.apply(el)));
  return resArray;
}

console.log(invoke2(['1','2','3'], parseInt)); // [NaN, NaN, NaN] - expected [123]
console.log(invoke2([['a','b','c'], ['d','e','f']], Array.prototype.join)); // ['a,b,c', 'd,e,f']

尝试3:尝试转发参数,但均报错

function invoke3 (collection, methodName, ...arg) {
  let resArray = [];
  _.each(collection, el => resArray.push(methodName.apply(el, ...arg)));
  return resArray;
}

console.log(invoke3(['1','2','3'], parseInt)); // [NaN, NaN, NaN] - expected [123]
console.log(invoke3([['a','b','c'], ['d','e','f']], Array.prototype.join, '')); // Uncaught TypeError: CreateListFromArrayLike called on non-object - expected ['abc', 'def']

注:已查看相关讨论,但本次需求中methodName并非字符串,暂未采用字符串方案,希望获得原理性提示而非直接答案,以便自行解决问题。

原理性提示(无直接答案)

  • 核心关注两个点:函数的调用上下文(this指向) 和 函数的参数传递规则
  • 普通函数(如parseInt)的调用上下文不影响功能,但参数数量、顺序严格固定;原型方法(如Array.prototype.join)的调用上下文必须是对应类型的实例,否则会触发类型错误
  • 回忆call/apply的双重作用:既可以改变函数的this指向,也能传递参数,注意apply的第二个参数必须是数组或类数组结构
  • 思考遍历集合时,每个元素的角色:调用目标方法时,哪些元素是方法的上下文,哪些是方法的参数?
  • 额外参数的转发逻辑:invoke接收的*arguments需要正确传递给目标方法,注意参数的拼接顺序——目标方法本身的参数和转发参数的优先级、顺序关系

内容的提问来源于stack exchange,提问作者nimbus4so

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:25:23