高阶函数——手写reduce、map、filter

237 阅读2分钟

高阶函数

1.高阶函数是至少满足下列一个条件的函数:

  • 接受一个或多个函数作为输入

  • 输出一个函数

    比如,数组自带的map、filter和reduce就是高阶函数,因为它们接受一个函数作为参数

      const array1 = [1, 4, 9, 16];
      const map1 = array1.map(x => x * 2);
      console.log(map1);    // [2, 8, 18, 32]

2.map、filter和reduce的实现过程却非常简单。需要注意下面三个问题:

  • 这三个方法在哪里创建?

    • 答:在Array.prototype上创建,这样才可以在实例上调用这几个方法
  • 怎么在这三个方法中找到arr并循环?

    • 答:this
  • 我实现的函数是map、filter和reduce的完全体么?

    • 答:想的很周到!真正的函数不仅仅接受一个参数,可以接受function callback(currentValue, index, array)作为参数

3.代码

3.1 手写map

  /*
    map映射数组(遍历数组),有return 返回一个新数组 
      callback的参数:
        value --当前索引的值
        index --索引
        array --原数组
  */

    let arr = [10, 20, 30, 40, 50]
    
    Array.prototype.myMap = function (callback) {
        /*
          function xx (item,index){
            return item * 2
          }
        */
        let tasks = [];                             // 返回新数组
        for (let i = 0; i < this.length; i++) {     // for循环数组的每一项 模拟循环功能
          let item = callback(this[i], i, this)     // 执行这个函数 传递实参
          tasks.push(item)                          // 将item推进数数组中
        }
        return tasks
    }

    // 谁调用我 我指向谁
    let result = arr.myMap(function (item, index) {
        return item * 2
    })

    console.log(result);

3.2 手写filter

/*
  
    过滤数组,返回一个满足要求的数组
      callback的参数:
        value --当前索引的值
        index --索引
        array --原数组
*/


  // 手写filter
  Array.prototype.myFilter = function (callback) {
    let task = []
    for (let i = 0; i < this.length; i++) {
      if (callback(this[i], i, this)) {
        task.push(this[i])
      }
    }
    return task
  }

  let result1 = arr.myFilter(function (value, index) {
    return value > 20
  })
  console.log(result1);



3.2 手写reduce

  /*
        不提供初始值 默认从1开始遍历 pre就是数组的第0项
        当第二次循环时 将第一次return的结果作为第二次循环的pre的值
        第一轮:10 20 1
        第二轮:30 66 2
        。。。
        第五轮:158 235 5
  */
  
  /*
        提供初始值 从索引0处开始遍历 pre为initValue,cur为arr[0]
        第一轮:0 10 0
        第二轮:10 20 1
        。。。
        第五轮:148 10 4
        第六轮:158 235 5
    */

  Array.prototype.myReduce = function (callback, init) {
    if (typeof callback !== "function") {
      throw new TypeError(`${callback} is not a function`);
    }

    let result = init || this[0];  // 是否赋有初始值 且上一次的结果

    for (let i = init ? 0 : 1; i < this.length; i++) {  // 没有就从1开始 有就从0开始
      result = callback(result, this[i], i, arr);  // 返回上一次的结果
    }

    return result;
  };



  let result3 = arr.myReduce((pre, cur, index, arrList)=>{
    return pre + cur
  })

  console.log(result3);