节流和防抖

防抖和节流属于性能优化,在进行窗口的resize、滚动条scroll,输入框内容校验等操做时,若是事件处理函数调用的频率无限制,会加剧浏览器的负担,致使用户体验很是糟糕。浏览器

此时咱们能够采用debounce(防抖)和throttle(节流)的方式来减小调用频率,同时又不影响实际效果。性能优化

函数防抖(debounce)

无论事件触发频率多高,必定在事件触发n秒后才执行,若是你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行。对于短期内连续触发的事件,防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。markdown

实现:

  • 实现的关键就在于setTimeout这个函数,因为还须要一个变量来保存计时,考虑维护全局纯净,能够借助闭包来实现。
  • 里面的setTimeout则用的箭头函数,这样作的意义是让this的指向准确,this的真实指向并不是debounce的调用者,而是返回闭包的调用者。
  • 对传入闭包的参数进行透传
function debounce(event, time) {
    let timer = null;
    return function(...args) {
      clearTimeout(timer);
      timer = setTimeout(()=> {
        event.apply(this, args);
      }, time)
    }
 }
 // 若是须要当即执行, 加一个flag 标志, 定时器变量`timer`为空时,说明是第一次执行,咱们当即执行它。
 
 function debounce(fn, time, flag) {
   let timer = null;
   return function(...args) {
    clearTimeout(timer);
    if(flag && !timer) {
       fn.apply(this, args)
    }
    timer = setTimeout(()=> {
       fn.apply(this, args);
    }, time)
   }
 }

复制代码

应用场景:

一、窗口的resize闭包

window.addEventListener('resize', debounce(handleResize, 200))
复制代码

二、滚动条scrollapp

function showTop() {
  const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log(scrolltop);
}
window.addEventListener('scroll', debounce(showTop, 1000))
复制代码

三、输入框内容校验, 搜索框函数

debounce(valicator/fetchSelectData, 1000)
复制代码

函数节流(throttle)

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

节流比如水龙头放水,按照必定规律在某个时间间隔内一滴一滴的往下滴, 不开阀放水浪费;fetch

函数节流主要有两种实现方法: 时间戳和定时器;优化

时间戳实现:

首刻发生,尾刻不发生,中间正常this

function throttle(event, time) {
    let pre = 0;
    return function(...args) {
       if(Date.now() - pre > time) {
          pre = Date.now();
          event.apply(this, args);
       }
    } 
}

复制代码

定时器实现

首刻不发生,尾刻发生,中间正常;

function throttle(event, time) {
  let timer = null;
  return function(...args) {
    if(!timer) {
       timer = setTimeout(()=>{
         clearTimeout(timer)
         timer=null;
         event.apply(this, args);
       }, time);
    }
  }
}
复制代码

结合

function throttle(event, time) {
  let pre = 0, timer = null;
  return function(...args) {
     if(Date.now() - pre > time) {
         pre= Date.now();
         timer = null
         clearTimeout(timer);
         event.apply(this, args)
     } else if(!timer) {
        timer = setTimeout(()=>{
          event.apply(this, args);
        }, time);
     }
  }
}
复制代码
相关文章
相关标签/搜索