防抖 & 节流

作者: Eileen_1d88 | 来源:发表于2019-10-10 22:12 被阅读0次

    防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时

    说到防抖,如果代码中我自己使用的话,可能我会直接这样写:

    var timer = null
    var time = 500
    function f(fn) {
      if (timer) {
        clearTimeout(timer)
        timer = null
      }
      timer = setTimeout(() => {
         fn.apply(this, arguments)
      }, time)
    }
    

    但是这样写的问题是非常明显的,代码毫无优雅性可言,并且一旦全局变量不小心被修改,这个函数就很可能无法正常执行,那么在这个基础上,我们可以一步步来完成一个防抖debounce。
    思路:
    1)首先我们明确知道我们需要传入的参数是一个fn和wait
    2)那么我们还有一个timer,很明显,这个timer对于传入的fn是一个全局变量,那么为了在一个function中始终能访问到这个变量timer,注定我们需要使用一个闭包来完成

    var debounce = function(fn, wait) {
        var timeout = null;
        return function() {
          if (timeout) {
            clearTimeout(timeout)
            timeout = null
          }
          timeout = setTimeout(() => {
            fn.apply(this, arguments)
          }, wait)
        }
      };
    

    节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数

    也就是说在一段时间内,这段时间内最后被触发的操作会被执行
    首先来一个最挫的实现:

    var delay = 500
      var timer
      function f(fn) {
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(this, arguments)
            timer = null
          }, delay)
        }
      }
    

    那么继续按照方才的思路来:
    1)要传的参数有2个: fn和delay
    2)同样timer是fn要访问的全局变量

    var throttle = function(fn, delay) {
        var timer = null;
        return function() {
             var args = arguments
             // 写的过程中在这里卡了一下,然后才反应过来,
             // 有timer的时候,后续的代码完全没有执行,所以取到的参数是
             // 第一次触发时的参数
            
            if (!timer) {
              timer = setTimeout(() => {
                fn.apply(this, args)
                timer = null
            }, delay)
        }
      }
    };
    

    写完这个之后,突然有一个感悟,有时候想写一个闭包的时候,可以先写一个很挫的不是闭包的函数来实现,然后再改成闭包的形式,现在觉得是这样,不知道是不是通用的,因为还没有懂得函数科里化😭

    相关文章

      网友评论

        本文标题:防抖 & 节流

        本文链接:https://www.haomeiwen.com/subject/rqzapctx.html