说一说js防抖节流的事情

387 阅读2分钟
防抖与节流函数是一种最常用的 高频触发优化方式,能对性能有较大的帮助。


你是否在日常开发中遇到一个问题,在滚动事件中需要做个复杂计算或者实现一个按钮的防二次点击操作。

这些需求都可以通过函数防抖动来实现。尤其是第一个需求,如果在频繁的事件回调中做复杂计算,很有可能导致页面卡顿,不如将多次计算合并为一次计算,只在一个精确点做操作。

PS:防抖和节流的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次,而节流的 情况会每隔一定时间(参数wait)调用函数。

防抖 (debounce)

防抖将多次高频操作优化为只在最后执行一次,使用的场景有很多,比如用户输入,只在用户最后输入完 在做校验;


/**
 * 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
 *
 * @param  {function} func        回调函数
 * @param  {number}   wait        表示时间窗口的间隔
 * @param  {boolean}  immediate   设置为ture时,是否立即调用函数
 * @return {function}             返回客户调用函数
 */
function debounce (func, wait = 50, immediate = true) {
   var timer;
   var context;
   var args;

   var later = function () {
      return setTimeout(function () {
         timer = null;
         if(!immediate){
            func.apply(context,args);
            context = args = null;
         }
      },wait)
   };

   return function () {
      //如果延迟函数不存在,就创建一个
      if(!timer){
         timer = later();
         // 如果是立即执行,调用函数
             // 否则缓存参数和调用上下文
         if(immediate){
            func.apply(context,args);
         }else{
            context = this;
            args = arguments;
         }
      }else{
         clearTimeout(timer);
         timer = later();
      }
   }
}

节流(throttle)

 每隔一段时间后执行一次,也就是降低频率,将高频操作优化成低频操作,通常使用场景: 滚动条事件 或者 resize 事件,

/**
 * 节流函数,每隔一段时间后执行一次,也就是降低频率,将高频操作优化成低频操作,
 *
 * @param  {function} func        回调函数
 * @param  {number}   wait        表示时间窗口的间隔
 * @param  {boolean}  immediate   设置为ture时,是否立即调用函数
 * @return {function}             返回客户调用函数
 */

 function throttle(func, wait=50, immediate=true) {
    var timer;
    var context;
    var args;

    var later = function () {
      return setTimeout(function () {
         if(!immediate){
            func.apply(context,args)
         }
         timer = context = args = null;
      },wait)
   };

    return function () {
      if(!timer){
         timer = later();
         if(immediate){
            func.apply(context,args);
         }else {
            context = this;
            args = arguments;
         }
      }

   }
}