封装数组常见方法

205 阅读1分钟
      //map方法
      Array.prototype.myMap = function (callback) {
        //result数组用于保存每次callback的结果,最后返回该数组。
        const result = [];
        for (let i = 0; i < this.length; i++) {
          result.push(callback(this[i], i, this));
        }
        return result;
      };

      //reduce方法
      Array.prototype.myReduce = function (callback, initialValue) {
        //result是最终的计算结果。一开始是初始值。
        let result = initialValue;
        //start开始遍历的下标。
        let start = 0;
        //要判断initialValue是否有值,无值时将数组第一个元素作为初始值。且从下标1开始遍历。
        if (initialValue === undefined) {
          result = this[0];
          start = 1;
        }
        for (let i = start; i < this.length; i++) {
          //计算result
          result = callback(result, this[i], i, this);
        }
        //计算完成返回result
        return result;
      };

      //filter方法
      Array.prototype.myFilter = function (callback) {
        const result = [];
        for (let i = 0; i < this.length; i++) {
          //符合条件的才添加到result数组中。
          if (callback(this[i], i, this)) {
            result.push(this[i]);
          }
        }
        return result;
      };

      //find方法
      Array.prototype.myFind = function (callback) {
        for (let i = 0; i < this.length; i++) {
          //返回第一个符合条件的元素
          if (callback(this[i], i, this)) {
            return this[i];
          }
        }
        //没有找到元素,返回undefined
        return undefined;
      };

      //findIndex方法
      Array.prototype.myFindIndex = function (callback) {
        for (let i = 0; i < this.length; i++) {
          //返回第一个符合条件元素的下标
          if (callback(this[i], i, this)) {
            return i;
          }
        }
        //没有找到元素,默认返回-1
        return -1;
      };

      //every
      Array.prototype.myEvery = function (callback) {
        for (let i = 0; i < this.length; i++) {
          //有一个不满足条件就返回false
          if (!callback(this[i], i, this)) {
            return false;
          }
        }
        return true;
      };

      //some
      Array.prototype.mySome = function (callback) {
        for (let i = 0; i < this.length; i++) {
          //有一个满足就返回true
          if (callback(this[i], i, this)) {
            return true;
          }
        }
        return false;
      };

      //push
      Array.prototype.myPush = function () {
        //需要遍历arguments。因为push方法可以接受不定参数添加到数组的队尾。
        for (let i = 0; i < arguments.length; i++) {
          //给数组队尾添加元素。 添加元素后length会自增1。所以每次都是添加到队尾。
          this[this.length] = arguments[i];
        }
        return this.length;
      };

      //unshift
      Array.prototype.myUnshift = function () {
        for (let i = 0; i < arguments.length; i++) {
          for (let j = this.length; j > 0; j--) {
            this[j] = this[j - 1];
          }
          this[0] = arguments[i];
        }
        return this.length;
      };

      //pop
      Array.prototype.myPop = function () {
        if (!this.length) return undefined;
        const end = this[this.length - 1];
        this[this.length - 1] = null;
        this.length = this.length - 1;
        return end;
      };

      //shift
      Array.prototype.myShift = function () {
        if (!this.length) return undefined;
        const start = this[0];
        for (let i = 1; i < this.length; i++) {
          this[i - 1] = this[i];
        }
        this.length = this.length - 1;
        return start;
      };

结论

  1. 高阶函数其实都是对普通的for循环进行了一次封装。如果不在callback对原数组进行修改,那么高阶函数也是不会修改原数组的。
  2. 封装时主体逻辑容易编写,但需要注意一些小问题。比如push方法接受不定数量的参数、reduce方法的默认值可以不传等情况。
  3. push、unshift方法添加元素时,length会自动修改。而pop、shift是不会自动修改的,需手动设置length。