一.什么是防抖和节流

函数防抖(debounce)

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新延时。
前端开发过程中的resize,scroll,mousemove,mousehover等,会被频繁触发,不做限制的话,有可能一秒之内执行几十次、几百次,如果这些函数内部执行了其他函数,尤其是执行了操作DOM的函数,那不仅会造成计算机资源的浪费,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。

函数节流(throttle)

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

二.防抖和节流的简单实现

  1. // 防抖函数
  2. let debounce = (fn, delay) => {
  3. let timer = null;
  4. return function (...args) {
  5. timer && clearTimeout(timer)
  6. timer = setTimeout(()=>{
  7. fn(...args)
  8. }, delay)
  9. }
  10. }

函数防抖存在的问题

如果,一直触发事件,且每次触发事件的间隔小于delay,那就无法触发。

  1. // 节流函数
  2. let throttle = (fn,delay)=>{
  3. let flag = true;
  4. return function(...args){
  5. if(!flag) return;
  6. flag=false
  7. setTimeout(()=>{
  8. fn(...args);
  9. flag=true
  10. },delay)
  11. }
  12. }

三.利用时间戳完善节流函数

我们都知道,有时候setTimeout会存在一定的误差,因为宏任务有时会被阻塞,这时候需要利用时间戳更好的优化我们的节流函数

  1. const throttle = (func, wait = 50) => {
  2. let lastTime = 0 // 上⼀一次执⾏行行该函数的时间
  3. return function(...args){
  4. let now = +new Date() // 当前时间
  5. if(now - lastTime > wait){
  6. // 将当前时间和上一次执行函数时间对比
  7. // 如果差值大于设置的等待时间就执行函数
  8. lastTime = now
  9. func.apply(this,args)
  10. }
  11. }
  12. }
  13. setInterval(
  14. throttle(() => {
  15. console.log(1)
  16. }, 500),
  17. 1
  18. )