高阶函数的应用

137 阅读5分钟

高阶函数

将另一个函数作为参数或将函数定义为返回值的函数称为高阶函数。

构建高阶函数

既然知道了高阶函数的定义,那我们就可以构建高阶函数了

1. 将函数作为参数

这种将函数作为参数的方法通常被用在回调函数中。 回调函数是在所有其他操作完成后在操作结束时执行的函数。如果将函数作为参数传入父元素中,并在父函数的其他操作都完成后再运行,这样可以处理回调函数的异步行为。

我们经常使用的js事件监听用的就是这种思想。

  const ele = document.getElementById('test');
  ele.addEventListener('animationstart', this.listener, false);
  listener(e) {
    const ele = document.createElement('li');
    switch (e.type) {
      case 'animationstart': 
        ele.innerHTML = 'Started: elapsed time is' + e.elapsedTime;
        break;
      case 'animationend': 
        ele.innerHTML = 'Ended: elapsed time is' + e.elapsedTime;
        break;
      case 'animationiteration': 
        ele.innerHTML = 'New loop started at time' + e.elapsedTime;
        break;
      default:
        break;
    }
    document.getElementById('output').appendChild(ele);
  }

当然也可以将函数体的内容以匿名函数写在参数里面。

const ele = document.getElementById('test');
  ele.addEventListener('animationstart', function(e) {
    const ele = document.createElement('li');
    switch (e.type) {
      case 'animationstart': 
        ele.innerHTML = 'Started: elapsed time is' + e.elapsedTime;
        break;
      case 'animationend': 
        ele.innerHTML = 'Ended: elapsed time is' + e.elapsedTime;
        break;
      case 'animationiteration': 
        ele.innerHTML = 'New loop started at time' + e.elapsedTime;
        break;
      default:
        break;
    }
    document.getElementById('output').appendChild(ele);
  }, false);

2. 将函数定义为返回值

将函数定义为返回值在函数科里化中用的比较多。

testAttitude(original, replacement, source) {
  return function(source) {
    return source.replace(original, replacement);
  }
}
const goodMan = this.testAttitude(/好人/ig, '坏人');
const badMan = this.testAttitude(/坏人/ig, '好人');
console.log(goodMan('我是一个好人,偶像,你挑的嘛'));   // 我是一个坏人,偶像,你挑的嘛
console.log(badMan('我是一个坏人,偶像,你挑的嘛'));    // 我是一个好人,偶像,你挑的嘛

常见的高阶函数及其应用

在实际开发中,我们常用的封装好的的高阶函数有很多。按照上面我们对高阶函数的定义,可以将高阶函数分为两类

函数作为参数

filter()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 如果找不到满足条件的数组,则返回undefined
  • 不会对空数组进行校验
  • 回调函数需要返回值
应用

过滤数组,返回满足条件的数组。

const arr = [0, 1, 3, 5, 7, 9];
const result = arr.filter((item, index) => {
  console.log(item, index);
  return item < 5;
})
console.log(arr);  // [0, 1, 3, 5, 7, 9]
console.log('返回结果', result);   // [0, 1, 3]

map()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 不会对空数组进行校验
  • 回调函数需要返回值
应用

对数组中的每一项进行相同的处理。

const arr = [0, 1, 3, 5, 7, 9];
const result = arr.map((item, index) => {
  console.log(item, index);
  return item * 2;
})
console.log(arr);  // [0, 1, 3, 5, 7, 9]
console.log('返回结果', result);  // [0, 2, 6, 10, 14, 18]

foreach()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 回调函数不需要返回值,因此总是返回undefined
  • 不会改变原来的数组
  • 空数组不会执行回调函数
应用

遍历数组,对数组进行处理

const arr = [0, 1, 3, 5, 7, 9];
const result = arr.forEach((item, index) => {
  console.log(item, index);
  item = 5;
})
console.log(arr);  // [0, 1, 3, 5, 7, 9]
console.log('返回结果', result);  // undefined

sort()

  • 需要传入一个回调函数
  • 回调函数有两个参数a(当前值),b(下一个值)
  • 会改变原来的数组
应用

对数组进行排序,升序或者降序

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 7, 9];
const result = arr.sort((a, b) => {
  console.log(a, b);
  return a - b;
})
console.log(arr);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('返回结果', result);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

findIndex()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 如果找不到满足条件的元素,则返回-1
应用

找到数组中满足条件的第一个元素的索引值index

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.findIndex((item, index) => {
  console.log(item, index);
  return item === 8;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 7, 9]
console.log('返回结果', result); // 5

some()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 如果找不到满足条件的数组,则返回false
  • 不会对空数组进行校验
应用

判断当前数组中是否存在某元素,存在则返回true, 否则则返回false

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.some((item, index) => {
  console.log(item, index);
  return item === 8;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 8, 9]
console.log('返回结果', result); // false

every()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 如果找不到满足条件的数组,则返回false
  • 只要有一项不满足条件,就不会继续往下执行了
  • 不会对空数组进行校验
应用

判断数组中的每一项是否都满足条件,满足返回true,只要有一项不满足就是false.

onst arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.every((item, index) => {
  console.log(item, index);
  return item >= 0;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 8, 9]
console.log('返回结果', result); // true

find()

  • 需要传入一个回调函数
  • 回调函数有两个参数item,index
  • 不会改变原来的数组
  • 如果找不到满足条件的数组,则返回undefined
  • 如果找到满足条件的值就不会继续往下找了
  • 不会对空数组进行校验
应用

找到数组中满足条件的元素,和some, findIndex类似,只是find返回的是元素本身,some返回的是布尔值,findIndex返回的是元素的索引index

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.find((item, index) => {
  console.log(item, index);
  return item > 0;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 8, 9]
console.log('返回结果', result); // 1

reduce()

  • 需要传入一个回调函数
  • 回调函数有四个参数pre(必须),current(必须),currentIndex(可选),arr(可选)
  • 不会改变原来的数组
应用

适用于对数组中的元素从左往右进行累计计算。

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.reduce((preVal, curVal) => {
  return preVal + curVal;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 8, 9]
console.log('返回结果', result); // 46

reduceRight()

  • 需要传入一个回调函数
  • 回调函数有四个参数pre(必须),current(必须),currentIndex(可选),arr(可选)
  • 不会改变原来的数组
应用

适用于对数组中的元素从右往左进行累计计算。

const arr = [0, 1, 2, 4, 6, 8, 3, 5, 8, 9];
const result = arr.reduceRight((preVal, curVal) => {
  return preVal + curVal;
})
console.log(arr); // [0, 1, 2, 4, 6, 8, 3, 5, 8, 9]
console.log('返回结果', result); // 46