数组方法手写

8/17/2022

# map

/**
 * map 默认会返回一个新数组,新数组中的内容为回调返回的内容组合而成。
 * 同时如果中间没有内容不可返回,应该直接跳过。比如数组为
 * arr[0]、arr[5],那么返回的应该只有两个的值,中间不存在的值不用返回
 * @param { Function } cb - 回调函数
 * @param { any } thisArg - 回调执行时候应该绑定的 this 参数
 */
Array.prototype.map = function (cb, thisArg) {
  if (this === null || this === undefined)
    throw new Error("Cannot read property 'map' of null or undefined!");
  if (typeof cb !== "function") throw new Error(cb + "is not a function");

  // 将 this 转换成对象
  const arr = Object(this);
  const res = [];
  for (let idx = 0; idx < arr.length; idx++) {
    // 当前下标存在才返回
    // 或者说是当前下标有值才返回
    if (idx in arr) {
      res.push(cb.call(thisArg, arr[idx], idx, arr));
    }
  }
  return res;
};

# reduce

/**
 *
 * @param { Function } cb - 回调函数,四个参数 previousVal,currentVal,idx,arr
 * @param {*} initialVal - 初始值
 * @returns
 */
Array.prototype.reduce = function (cb, initialVal) {
  if (this === null || this === undefined)
    throw new Error("Cannot read property 'map' of null or undefined!");
  if (typeof cb !== "function") throw new Error(cb + "is not a function");
  // 如果数组为空 且 没有初始值则会报错
  if (this.length === 0 && initialVal === undefined)
    throw new Error("Reduce of empty array with no initial value");
  // 如果数组为空则直接返回 initialVal
  if (this.length === 0) return initialVal;
  let arr = Object(this);
  // 正常情况循环从 0 开始,但是如果数组开始没有值,需要找到第一个有值的下标
  let i = 0;
  let res = initialVal;
  // 当没有传递 initialVal 的时候
  // initialVal 赋值为 arr 的第一个存在的值,同时遍历时候需要跳过
  if (!initialVal) {
    for (; i < arr.length; i++) {
      if (i in arr) {
        res = arr[i];
        i++;
        break;
      }
    }
  }
  for (; i < arr.length; i++) {
    // 仍然需要判断存在
    if (i in arr) {
      res = cb(res, arr[i], i, arr);
    }
  }
  return res;
};

# filter

Array.prototype.filter = function (cb, thisArg) {
  if (this === null || this === undefined)
    throw new Error("Cannot read property 'map' of null or undefined!")
  if (typeof cb !== 'function') throw new Error(cb + 'is not a function')

  const arr = Object(this)
  const res = []
  for (let i = 0; i < arr.length; i++) {
    if (i in arr) {
      let bool = cb(arr[i], i, arr)
      bool && res.push(arr[i])
    }
  }
  return res
}