javascript的防抖和节流

防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定onkeyup事件发请求去服务端检查,用户输入过程中,事件的触发频率也会很高,会导致大量的请求发出,响应速度会大大跟不上触发。

针对此类快速连续触发和不可控的高频触发问题,debounce 和 throttling 给出了两种解决策略;
 

防抖:所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

节流:所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

防抖和节流的区别:

防抖:在高频发的事件调用时,每次将定义好的定时器清除掉,只有当高频发事件调用最后一次的时候,由于没有再调用该事件函数,没有清除定义的定时器,那么定时器将正常工作,即定时器等待时间内连续调用10次后显示1,连续调用20次后显示的还是1。通俗来讲就是,你要我搬十几块砖,我偷懒,我最后才搬一块。

节流:在高频发的事件调用时,不会清除定义好的定时器。假设你的定时器为1s,加入if判断语句,如果你高频发事件的调用间隔小于1s,那么你在这1s的定时器等待时间内调用的次数都当成一次,即连续调用10次后显示10、连续调用20次后显示20。注意,虽然是显示20、30   但是其将若干函数调用合成为一次,并在给定时间过去之后,调用一次(仅仅只会调用一次)。通俗来讲就是,你要我搬十几块砖,我搬,不过我每1s(定时器范围)才搬一块,多了我不干。

示例代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>javascript防抖和节流</title>
    <style>
        #content{
            height: 150px;
            line-height: 150px;
            text-align: center;
            font-size: 18px;
            color: white;
            background-color: gray;
        }
    </style>
</head>
<body>
    <div id="content" >0</div>
    <script>
        var content = document.getElementById('content');    
        var num = 1; 
        function count(){  //基础操作          
            content.innerHTML = num++;
        }

        // content.onmousemove = function(){//没有防抖节流
        //     count();
        // }

        //防抖
        function debounce(func, wait) {
            var timeout;//声明一个定时器
            return function () {

                if (timeout){//每次调用函数都先清除定时器
                    clearTimeout(timeout);
                } 
                
                timeout = setTimeout(function(){
                    func();//延迟调用函数
                }, wait);
            }
        }
        // content.onmousemove = debounce(count,500);
        
        //节流
        // 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
        function throttle1(func, wait) {//时间戳版
            var lastTime = 0;
            return function() {
                var currentTime = Date.now();
                if (currentTime - lastTime > wait) {//如果调用时间间隔大于定时器规定时间,执行函数
                    func();
                    lastTime = currentTime;//重置上一次函数被调用时的时间
                }
            }
        }
        // content.onmousemove = throttle1(count,1000);

        function throttle2(func, wait) {//定时器版
            var timeout;//定义定时器
            return function() {
                if (!timeout) {//如果未定义定时器
                    timeout = setTimeout(function(){
                        func();
                        timeout = null;//释放定时器                  
                    }, wait)
                }
            }
        }
        content.onmousemove = throttle2(count,1000);


    </script>
</body>
</html>

参考链接:https://www.jianshu.com/p/c8b86b09daf0

猜你喜欢

转载自blog.csdn.net/CWH0908/article/details/89712442