程序员

防抖 & 节流

2019-10-10  本文已影响0人  Eileen_1d88

防抖:在事件被触发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)
    }
  }
};

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

上一篇下一篇

猜你喜欢

热点阅读