JS的防抖与节流

1、提出以下一种场景

(1)搜索框搜索条目的时候,每次onkeyup都会触发一次请求,返回xhr文件,一直输入11111,则每次都会请求。

(2)IE中使用onresize事件处理程序的时候,需根据浏览器窗口大小,来对dom进行频繁操作,改事件也会连续触发。

只要是代码是周期性执行的,都应该使用节流。

目的:防止回调函数每一次都执行

定义:

函数防抖是要在每完成等待某个时间后去执行某函数,而是要每间隔某个时间去执行某函数,避免函数的过多执行。

阿里巴巴是防抖(setTimeout隔一段时间去执行某函数)。淘宝是节流(以周期发送关键字)

RXJS里面有防抖和节流的封装。

2、防抖的实现代码

var container=document.getElementById("container");
 function getUserAction(){
  container.innerHTML =count++;
}
container.onmousemove= debounce(getUserAction,1000);

 function debounce(fn,wait){
   var timeout;
   return function(){
     clearTimeout(timeout);
     timeout=setTimeout(fn,wait)
   }
 }

 触发多次onmousemove事件,只会执行最后一次setTimeout(),1s后执行getUserAction

继续增强代码,在执行getUserAction()函数时,我们调用debounce 函数,并不知道外面的div容器是container,所以把container转化为this。

而getUserAction()函数里面的this,是window,因为fn最终在setTimeout()函数里面执行

可以用bind或者apply改变this指向

 function debounce(fn,wait){
   var timeout;
   return function(){
     clearTimeout(timeout);
     console.log(this)
     timeout=setTimeout(fn.bind(this),wait)
   }
 }

输出为

使用apply

function debounce(fn,wait){
  var timeout;
  return function(){
    clearTimeout(timeout);
    var that=this;
    timeout=setTimeout(function(){
      fn.apply(that)
      },wait)
  }
}

 新的需求:开始边界,在鼠标一移入时则加1 ,之后某一周期内执行一次

function debounce(fn,wait,flag){
   var timeout;
   return function(){
     if(flag){
      //判断是第一次进来则调用一次fn
      var pd=!timeout;  //pd为true,则是第一次进来
       clearTimeout(timeout)
       timeout = setTimeout(fn.bind(this), wait)
       console.log(pd);
      if(pd){
            fn.apply(this)
      }
     }else {
       clearTimeout(timeout);
       timeout = setTimeout(fn.bind(this), wait)
     }
   }
 }

 这样就实现了在鼠标一进入count立马加1,之后都是无数次触发后,最后一次执行fn

3、节流的实现代码

  function throttle(fn,wait){
    var previous=0;//参照物
    return function(){
      var now=new Date();
      console.log(now);
      var now1=+new Date();
      console.log(now1)
      if(now-previous>wait){
        console.log(this)
        fn.apply(this);
        previous=now
      }
    }
  }

输出:

如果new Date()前面有加号,会把标准时间转换为时间戳。这里用Date.now()也可以取到时间戳。

用setTimeout也可以实现节流

function throttle(fn,wait) {
  var timeout;
  return function () {
    var that = this;
    if (!timeout) {
      timeout = setTimeout(function () {
        fn.apply(that);
        timeout=null;
      }, wait)
    }
  }
}

注意,这里用了timeout=null;而不是clearTimeout(timeout);

clearTimeout()返回的是一个整数,所以进入一次if,执行一次fn,再也不执行。

另外,注意到此处用的是apply,而不是bind,因为apply是时间1s到了立刻执行,而bind是事先绑定(预处理),等需要执行的时候再执行fn

4、防抖和节流的异同

相同点不同点
都是为了避免多次重复连续执行某一函数

1、防抖:必须在一个周期后去执行事件触发的函数,即连续触发事件,只

在最后一次触发时去执行函数

2、节流:在不断的触发事件,这一段时间内,按一定周期去执行函数

throttle-函数节流:一个水龙头在滴水,可能一次性会滴很多滴,但是我们只希望它每隔 500ms 滴一滴水,保持这个频率。即我们希望函数在以一个可以接受的频率重复调用。

debounce-函数防抖:将一个弹簧按下,继续加压,继续按下,只会在最后放手的一瞬反弹。即我们希望函数只会调用一次,即使在这之前反复调用它,最终也只会调用一次而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值