手写 JS 数组核心方法

补充阅读:如果你对 thisArg的作用 或者prototype挂载的写法感到困惑,建议先了解 this 绑定机制和原型链:

  1. 三句话记住 call、apply、bind

  2. 箭头函数与 this 指针 —— 从根源到实践

  3. 原型链 —— 从 new 一个对象到方法共享的本质

forEach

对数组的每个元素执行一次提供的回调。

arr.forEach(callback(element, index, array), thisArg)

Array.prototype.myForEach = function (callback, thisArg) {
  for (let i = 0; i < this.length; i++) {
    callback.call(thisArg, this[i], i, this);
  }
};

直接遍历;关键细节是通过 call() 绑定 thisArg。

map

返回一个新数组,其元素为原数组每个元素经回调处理后的结果。

arr.map(callback(element, index, array), thisArg)

Array.prototype.myMap = function (callback, thisArg) {
  const result = new Array(this.length);
  for (let i = 0; i < this.length; i++) {
    result[i] = callback.call(thisArg, this[i], i, this);
  }
  return result;
};

预分配等长数组,遍历映射填充。

filter

返回一个新数组,包含所有通过回调测试的元素。

arr.filter(callback(element, index, array), thisArg)

Array.prototype.myFilter = function (callback, thisArg) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    if (callback.call(thisArg, this[i], i, this)) {
      result.push(this[i]);
    }
  }
  return result;
};

遍历并按条件收集,仅将满足断言的元素推入结果。

reduce

对每个元素执行归约函数,最终汇聚为单一输出值。

arr.reduce(callback(accumulator, currentValue, index, array), initialValue)

Array.prototype.myReduce = function (callback, initialValue) {
  let acc, startIndex;
  if (arguments.length >= 2) {
    acc = initialValue;
    startIndex = 0;
  } else {
    acc = this[0];
    startIndex = 1;
  }
  for (let i = startIndex; i < this.length; i++) {
    acc = callback(acc, this[i], i, this);
  }
  return acc;
};

通过归约函数累积;arguments.length 用于区分「未传初始值」和显式传入 undefined。