高阶函数 | 青训营笔记

92 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第 4 天

前言

高阶函数HOF(Higher Order Function)是JS中进阶部分的重要内容之一,高阶函数会接收一个或者多个函数作为参数,并输出一个函数作为返回值。高阶函数常被应用于当代web开发中,例如节流函数或者定时输出函数,在JS的内置方法中也有高阶函数的存在,例如reduce、sort和map等等。本篇文章将会介绍一些常见的高阶函数

高阶函数示例

在本章将会为大家介绍几个高阶函数:①节流函数、②定时输出函数、③只执行一次函数

1. 节流函数

在前端开发中,我们通常会定义一个元素的事件,例如click事件或者mouseup事件等等,当我们短时间内一直触发这些事件,但实际上一些操作我们不希望记录触发太多次事件,触发太多次事件会浪费计算机的资源导致运行速度减慢,于是我们引入了节流函数的概念。

我们借助定时器作为辅助,传入的第一个参数为需要节流的事件函数第二个参数为触发事件的时间间隔

/**
* 函数节流
* 500ms内多次点击只会算一次 
* @param {Function} fn 需要进行节流的函数
* @param {Number} cycle 每次执行指定函数的间隔时间,默认值为500ms
* @return {Function} fn 指定的函数
*/
function throttle(fn, cycle = 500) {
    let _timer;
    return function (...args) {
        if (_timer == null) {
            fn.apply(this, args);
            _timer = setTimeout(() => {
              _timer = null;
            }, cycle);
          }
        };
      }

根据上方的代码分析,我们的节流函数控制流量主要通过以下几个步骤:

  1. 定义一个变量_timer代表定时器是否存在
  2. 进行判断此时的定时器是否存在
  3. 若存在,说明上一个函数还未执行完成
  4. 若不存在,则重新创建一个定时器

2. 定时输出函数

定时输出表示当我们执行JS代码的时候,计算机的运算速度非常快,会在很短的时间内执行并输出我们的执行结果,如果我们需要控制台或者是前端页面不“那么快”的输出,可以引入定时输出函数。

与节流函数一致,需要传入两个参数,第一个是执行的函数第二个是间隔的时间

/**
 * 间隔执行函数
 * @param {Function} fn 
 * @param {number} time 
 * @returns {Function} fn
 */
function consumer(fn, time = 1000) {
    let tasks = [], timer;
    return function (...args) {
        tasks.push(fn.bind(this, ...args))
        if (timer == null) {
            timer = setInterval(() => {
                tasks.shift().call(this)
                if (tasks.length <= 0) {
                    clearInterval(timer)
                    timer = null
                }
            }, time);
        }
    }
}

如果已经理解了上一节的节流函数的执行步骤,其实定时输出函数也是同样的原理,执行步骤是:

  1. 定义tasks为任务列表,timer作为辅助变量帮助我们判断定时器是否存在
  2. 将需要执行的任务丢到任务执行列表中
  3. 判断定时器是否存在,如果存在则等待
  4. 如果定时器不存在说明上一个任务已经执行完毕,我们执行继续执行下一个函数

只执行一次函数

其实了解了以上两个函数后,对应执行一次的函数其实大家应该也有了自己的想法。顾名思义,该函数就是为了控制事件的执行次数,当多次触发事件的时候,只执行一次事件,后续多次触发事件无效。

/**
* 执行一次函数
* @param {Funcion} fn
* @return {Function} fn
*/
function once(fn) {
    return function(...args) {
        if(fn){
            const ret = fn.apply(this, args)
            fn = null
            return ret
        }
    }
}

这一个函数的执行的原理其实一目了然,步骤就是传入一个函数,如果没执行过就执行该函数,之后把该函数赋予null值,这样后续再传入同一个函数的时候就不会继续执行这个函数了。

总结

在青训营中月影老师还为我们介绍了更多的高阶函数及其使用方法,但无论是JS或者是HTML部分,都有更多的更深的内容等待我们大家去探索,高阶函数作为JS中进阶部分的内容理解起来可能会有一些困难,但是了解其原理后实现起来并不是难事,相信不久后的大家都会在顶峰相见。