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

如何定义无需传入数组参数的Array.prototype.myReduce方法

实现符合原生行为的Array.prototype.myReduce

你的代码核心问题出在用箭头函数定义原型方法和错误传入数组参数上,下面是完全对齐原生Array.reduce行为的修正实现:

错误点拆解

  1. 箭头函数没有自身的this,会继承外层作用域的this,导致无法在原型方法里获取到调用的数组实例,这也是你不得不手动传array的原因。
  2. 原生reduce不需要传入数组,因为调用时是数组实例直接触发方法,方法内部通过this就能拿到当前数组。
  3. 你的实现没有处理无初始值和空数组的边界情况,这是原生reduce的必要校验逻辑。
  4. 回调参数顺序写反了:原生reduce的回调第一个参数是累加器,第二个才是当前元素。

正确实现代码

Array.prototype.myReduce = function(callback, initialVal) {
  // 校验调用对象是否为数组
  if (!Array.isArray(this)) {
    throw new TypeError('myReduce called on non-array');
  }
  // 校验回调是否为函数
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }

  const arr = this;
  let accumulator;
  let startIndex = 0;

  // 处理无初始值的情况
  if (arguments.length < 2) {
    // 空数组且无初始值,抛出错误(对齐原生逻辑)
    if (arr.length === 0) {
      throw new TypeError('Reduce of empty array with no initial value');
    }
    // 取数组第一个元素作为累加器初始值,从第二个元素开始遍历
    accumulator = arr[0];
    startIndex = 1;
  } else {
    accumulator = initialVal;
  }

  // 遍历执行回调,对齐原生参数顺序:累加器、当前元素、索引、原数组
  for (let i = startIndex; i < arr.length; i++) {
    accumulator = callback(accumulator, arr[i], i, arr);
  }

  return accumulator;
};

使用示例

// 带初始值求和
console.log([1,2,3].myReduce((a,b) => a + b, 10)); // 输出 16

// 不带初始值求和
console.log([1,2,3].myReduce((a,b) => a + b)); // 输出 6

// 处理对象数组
const objArr = [{count:1}, {count:2}, {count:3}];
console.log(objArr.myReduce((total, item) => total + item.count, 0)); // 输出 6

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:07:03