数组常用方法以及实现

183 阅读3分钟

数组拓展

Array.prototype.forEach

forEach() 方法对数组的每个元素执行一次给定的函数。给定的函数有三个参数

  1. currentVal: 当前正在处理的元素
  2. index(可选): 当前元素索引
  3. self(可选): 数组本身 除了传给定函数外,还可以再传一个参数,这个参数将决定给定函数执行时内部 this 指向

forEach 的实现

Array.prototype.myForEach = function (callback, _this = window) {
  if (Object.prototype.toString.call(this) !== "[object Array]") {
    throw new Error("must be Array");
  }
  let arr = this;
  for (let i = 0; i < arr.length; i++) {
    callback.call(_this, arr[i], i, arr);
  }
};

Array.prototype.filter

filter() 方法创建一个新数组, 其包含通过所提供函数筛选的所有元素。参数与 forEach() 相同

filter的实现

Array.prototype.myFilter = function (callback, _this = window) {
  if (Object.prototype.toString.call(this) !== "[object Array]") {
    throw new Error("must be Array");
  }
  let arr = this;
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    if (callback.call(_this, arr[i], i, arr)) {
      result.push(arr[i]);
    }
  }
  return result;
}

Array.prototype.map

map() 方法创建一个新数组,其结果是该数组中的每个元素调用一次提供的函数后的返回值。参数与 forEach() 相同

map的实现

Array.prototype.myMap = function (callback, _this = window) {
  if (Object.prototype.toString.call(this) !== "[object Array]") {
    throw new Error("must be Array");
  }
  let arr = this;
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    result.push(callback.call(_this, arr[i], i, arr));
  }
  return result;
}

Array.prototype.every

every() 方法测试数组内所有元素是否都能通过给定函数的测试,都通过返回 true ,只要有1个不通过返回 false 。参数与 forEach 相同

every的实现

Array.prototype.myEvery = function (callback, _this = window) {
  if (Object.prototype.toString.call(this) !== "[object Array]") {
    throw new Error("must be Array");
  }
  let arr = this;
  for (let i = 0; i < arr.length; i++) {
    // 有一个没通过直接返回false
    if (!callback.call(_this, arr[i], i, arr)) {
      return false;
    }
  }
  // 全部通过返回true;
  return true;
}

Array.prototype.some

some() 方法测试数组中是不是至少有1个元素通过了给定函数测试,有一个通过返回 true ,没有一个通过返回 false

some的实现

some 的实现与 every 类似,只需在循环中判断是否有通过测试的元素有就直接返回 true,循环结束仍未找到则返回 false

Array.prototype.reduce

reduce() 方法第一个参数是一个函数,该函数接收四个参数;第二个参数是 initiaValue

  • callback
  1. accumulator: 累计器,它的值是上一次函数的返回值。
  2. currentValue: 数组正在处理的值
  3. index(可选): 数组当前元素索引
  4. self: 调用 reduce 方法的数组本身
  • initiaValue 作为第一次传入函数的第一个参数的值,如果没有传入则为数组第一项的值,从数组第二项开始调用回调函数

reduce 方法在没有传入 initiaValue 使用时需要注意以下几个点

  1. 如果调用 reduce 方法的数组长度为0时会报错 Reduce of empty array with no initial value
  2. 如果调用 reduce 方法的数组长度为1时,reduce 方法会直接返回数组第一项而不会去调用 callback
  3. 如果调用 reduce 方法的数组长度大于1时,则会直接从数组第二项开始调用 callback ,函数第一个参数则为数组第一项的值

reduce的实现

Array.prototype.myReduce = function (callback, ...arg) {
  if (Object.prototype.toString.call(this) !== "[object Array]") {
    throw new Error("must be Array");
  }
  let arr = this;
  let i = 0;
  // 如果没有传入第二个参数且数组长度为0直接报错
  // 长度为1则直接返回数组第一项
  // 长度大于1直接从数组第二项开始循环
  if (arg.length === 0) {
    if (arr.length === 0) throw new Error("Reduce of empty array with no initial value");
    else if (arr.length === 1) return arr[0];
    else i = 1;
  }
  let result = arg[0];
  for (i; i < arr.length; i++) {
    result = callback(result, arr[i], i, arr);
  }
  return result;
}