js中的防抖和节流

一、目的:防止函数被无意义高频调用
二、理解:
1、防抖(debounce)

本质:函数在特定的时间内不再被调用后执行

原理:设置一个定时器,如果在设定的时间间隔内事件再次触发,就会清除上一次的定时器并重新设置和计时,直到指定时间间隔内没有再次触发,才会执行函数

缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟

使用场景:文本框输入搜索(连续输入时避免多次请求接口)

个人通俗理解:事件连续触发,只执行最后一次回调函数

示例如下:

function showTop  () {
  var scrollTop = document.body.scrollTop ||document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
function debounce(fn, delay) {
  let timer = null; //借助闭包
  return function () {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(fn, delay) 
  }
}
window.onscroll=debounce(showTop,200)
2、节流(throttle)

本质:确保函数特定的时间内至多执行一次

原理:用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 规定时间段,如果是,则执行,并更新上次执行的时间戳

使用场景:resize、scroll、mousemove等事件触发监听

个人通俗理解:事件触发,函数执行,一定时间内函数无法再次执行

示例如下:

function showTop  () {
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
function throttle(fn,delay){
  let valid = true;
  return function() {
  //
    if(!valid){
      return false
    }
    valid = false;
    setTimeout(() => {
       fn();
       valid = true;
      }, delay)
   }
}

请注意,节流函数并不止上面这种实现方案,例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。也可以直接将setTimeout的返回的标记当做判断条件判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样

三、总结

总结:
函数防抖:将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否有延迟调用函数未执行。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

本文参考自:https://segmentfault.com/a/1190000018428170和https://www.jianshu.com/p/3d3f62b9d0ad和https://blog.csdn.net/zuorishu/article/details/93630578

你可能感兴趣的:(js中的防抖和节流)