防抖和节流

1.应用场景:

js的一些事件:如keyup、onresize、scroll、mousemove、mousehover等;还有类似于:手抖、手滑、手误、服务器没有响应或者响应慢等的重复点击操作。

(2019-03-21)优化成下面:

  • 防抖:
    • search搜索联想,用户在不断输入值时,用防抖来节约请求资源;
    • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次;
    • 防止重复提交;
  • 节流:
    • 鼠标不断点击触发,mousedown(单位时间内只触发一次);
    • 监听滚动事件,比如是否滑到底部加载更多,用throttle来判断。
  • 再增加一点:防抖和节流的作用
    • 为了减少不必要的计算;
    • 不浪费资源;
    • 只在适合的时候进行计算。

2.共同点:

均是用来控制某个函数在一定时间内执行多少次的技巧。两种方法都是用来提高前端性能,减轻浏览器压力。

(2019-03-21)优化成下面:

防止某一时间频繁触发事件。

3.区别:

3.1 什么是防抖(debounce)?

延时处理,在事件被触发N秒后再执行回调,如果在这N秒内又被触发,则重新开始计时。

(2019-03-21)增加下面:

  • 某一时间段内,只能触发一次,周期内不能再次触发,直到停止后,才可以执行。
window.addEventListener('resize',function(e){
    var t;
    return function(){
        if(t) clearTimeout(t);
        t = setTimeout(function(){
            // do something...
        },500);
    }
}());

3.2 什么是节流(throttle)?

让一个函数无法在很短时间内连续调用,当上一次函数过了规定的这个时间段后,才能进行下一次该函数的调用。

(2019-03-21)增加下面:

  • 每隔一个周期,执行一次
function throttle(func, waitTime) {
    var timeout,
        previous = 0;
    return function() {
        context = this;
        args = arguments;
        if (!timeout) {
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(context, args)
            }, waitTime)
        }
    }
}

(2019-03-21)防抖和节流实现函数增加下面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>防抖与节流</title>
<style>
  #container {
      400px;
      height: 200px;
      line-height: 200px;
      text-align: center;
      color: #ffffff;
      background-color: #333;
      font-size: 30px;
  }
</style>
</head>
<body>
   <div id="container"></div>
</body>
<script>
    //防抖和节流的作用: 为了减少不必要的计算,不浪费资源,只在适合的时候进行计算
    // var count = 1;
    // var container = document.getElementById('container');
    // function getUserAction(){
    //     //大量的算法、逻辑、异步、回调
    //     console.log(this);
    //     container.innerHTML = count++;
    // }
    // container.onmousemove = debounce(getUserAction,1000,true);

    // //防抖
    // function debounce(func,wait,flag){
    //     var timeout;
    //     var self = this;
    //     return function(){
    //         clearTimeout(timeout);
    //         if(flag){//开始边界  就去就是做
    //             var callnow = !timeout;//callnow:当前状态  
    //             timeout = setTimeout(function(){
    //                 timeout=null;
    //             },wait);
    //             if(callnow){
    //                 func.apply(self);
    //             }
    //         }else{
    //             timeout = setTimeout(function(){
    //                 func.apply(self);//为啥this没有代表 <div id="container"></div>?
    //             },wait);
    //         }
    //     }
    // }
    //可以控制边界
    // 开始边界  与  结束边界

    // 事件执行一个方法,返回一个方法


    //节流
    var count = 1;
    var container = document.getElementById('container');
    function getUserAction(){
        //大量的算法、逻辑、异步、回调
        container.innerHTML = count++;
    }
    container.onmousemove = throttle(getUserAction,5000);

    function throttle(func,wait){
        //用定时器或者时间戳均可以写
        var prexious = 0;//用做标记
        return function(){
            var self = this;
            var now = +new Date();//+new Date() 返回13位的时间戳,毫秒数;将会调用Date原型上的valueOf方法,等同于Date原型上的getTime()方法
            if(now - prexious > wait){
                func.apply(self);
                prexious = now;
            }
        }
    }



</script>
</html>

4.文字举例:

A同学从B地到C地,防抖就相当于A同学坐公交车(乘客源源不断的刷卡上车,直到司机看见无人刷卡后,才会发车,即一段时间内,回调函数只会调用一次,即触发事件的最后一次);节流就相当于A同学坐地铁(在规定的停车,在规定的时间发车,即在一段时间内,会每隔一段时间调用一次)。

(2019-03-21)总感觉这段文字解释不太好理解,先划掉吧~

5.结语:

  • 听说这是个高频面试题,且先记下。
原文地址:https://www.cnblogs.com/zhengyeye/p/10572605.html