模拟实现数组中的map、reduce、filter等方法

601 阅读2分钟

map方法

一个由原数组每个元素执行回调函数的结果组成的新数组

     // thisArg(可选参数):执行callback函数时值被用作this 
    Array.prototype.map = function (callbackFn, thisArg) {
      // 处理数组类型异常
      if (this === null || this === undefined) {
        throw new TypeError("Cannot read property 'map' of null or undefined")
      }
      // 处理回调函数类型异常
      if (Object.prototype.toString.call(callbackFn) != "[object Function]") {
        throw new TypeError(callbackFn + "is not a function");
      }
      // 先转成对象
      let O = Object(this);
      let T = thisArg;
      let len = O.length >>> 0;
      let A = new Array(len);
      for (let k = 0; k < len; k++) {
        // in:表示在原型链上查找,使用hasOwnProperty:表示只能找私有属性
        for (k in O) {
          let kValue = O[k];
          let mappedValue = callbackFn.call(T, kValue, k, O);
          A[k] = mappedValue;
        }
      }
      return A;
    }

reduce方法

对数组中的每个元素执行一个由您提供的回调函数,将其结果汇总为单个返回值

 //initalValue: 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。
    Array.prototype.Myreduce = function (callbackfn, initialValue) {
      if (this === null || this === undefined) {
        throw new TypeError("Cannot read property 'reduce' of null or undefined");
      }
      if (Object.prototype.toString.call(callbackfn) != '[object Function]') {
        throw new TypeError(callbackfn + ' is not a function')
      }
      let O = Object(this);
      let len = O.length >>> 0;
      let k = 0;
      let accumulator = initialValue;
      // initialValue为空时,使用数组中的第一个元素。
      if (accumulator === undefined) {
        for (; k < len; k++) {
          // 查找原型链
          if (k in O) {
            accumulator = O[k];
            k++;
            break;
          }
        }
      }
      //  表示:在没有初始值的空数组上调用 reduce 将报错
      if (k == len && accumulator === undefined) {
        throw new TypeError('Each element of the array is empty');
      }
      for (; k < len; k++) {
        if (k in O) {
          // 这是一个累计器
          accumulator = callbackfn.call(undefined, accumulator, O[k], k, O);
        }
      }
      return accumulator;
    }

filter方法

创建一个新数组,其包含通过提供函数实现的测试的所有元素

    // thisArg:执行 callback 时,用于 this 的值
    Array.prototype.Myfilter = function (callbackfn, thisArg) {
      // 处理数组类型异常
      if (this === null || this === undefined) {
        throw new TypeError("Cannot read property 'filter' of null or undefined");
      }
      // 处理回调类型异常
      if (Object.prototype.toString.call(callbackfn) != '[object Function]') {
        throw new TypeError(callbackfn + "is not a function");
      }
      let O = Object(this);
      let len = O.length >>> 0;
      let resLen = 0;
      let res = [];
      for (let i = 0; i < len; i++) {
        if (i in O) {
          let elment = O[i];
          if (callbackfn.call(thisArg, O[i], i, O)) {
            res[resLen++] = elment;
          }
        }
      }
      return res;
    }

push方法

返回新数组的长度

    Array.prototype.mypush = function (...items) {
      let O = Object(this);
      let len = O.length >>> 0;
      // 参数的长度
      let argCount = items.length >>> 0;
      if (len + argCount > 2 ^ 52 - 1) {
        throw new TypeError("The number of array is over the max value restricted!");
      }
      for (let i = 0; i < argCount; i++) {
        O[len + i] = items[i];
      }
      let newLength = len + argCount;
      O.length = newLength;
      return newLength;
    }

pop方法

返回被删除的元素

    Array.prototype.pop = function () {
      let O = Object(this);
      let len = O.length >>> 0;
      if (len === 0) {
        O.length = 0;
        return undefined;
      }
      len--;
      // 数组最后一个值
      let value = O[len];
      delete O[len];
      O.length = len;
      return value;
    }