JavaScript 节流/防抖

先来说一下节流,节流可以用来优化网络请求性能。它的思想是:对于一个事件,为该事件绑定节流函数之后可以让该事件在给定的时间间隔内只能被执行一次。怎么做到的呢,设置一个计时器,每次执行事件时首先判断本次事件的执行距离上次执行时间是否大于给定的时间间隔,若小于给定的时间间隔,则事件不予执行;若大于给定的时间间隔,则执行事件,并更新计时器的值。
节流的应用场景有:对于点击按钮需要与后台通信的情况,比如双十一的抢购按钮,为该按钮的点击事件添加节流函数可以缓解服务器压力,使得一定时间间隔内该按钮只能被有效点击一次。

再来说一下防抖,防抖可以用来优化页面请求性能。它的思想是:不希望某个事件在短时间内疯狂触发,影响性能,所以我们设置一个定时器,让这个事件在一定时间延迟后再执行,如果这个延迟中间这个事件又触发了,那就把上次事件绑定的定时器取消,避免了上次事件执行,然后重新设置一个定时器绑定在当前事件上。
防抖的应用场景有:搜索框input事件;鼠标移动mousemove事件;视窗大小变化resize事件…
节流与防抖的代码实现如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节流/防抖</title>
</head>
<body>
    <div style="border: red 1px solid; width: 500px; background-color: aqua">
        <h1>节流</h1>
    <div id="num">0</div>
    <button id="btn">click</button>
        </div>
    <br/>
    <div style="border: red 1px solid; width: 500px; background-color: #c938ff">
        <h1>防抖</h1>
    <input type="text" id="inp">
    </div>
    <script>  // 节流
        var oDiv = document.getElementById("num");
        var oBtn = document.getElementById("btn");

        function throttle(handler, wait){// 第一个参数为主要函数,第二个参数为毫秒
            var lastTime = 0;//记录过去的时间
            return function(){
                var nowTime = new Date().getTime(); //获取时间戳
                if(nowTime - lastTime > wait){
                //用时间戳记录当前时间,当前时间减去上一次的时间,如果大于 wait(你设置的 1000毫秒) 说明 过去1000毫秒了,
                //用户可以点击第二次了。
                    handler.apply(this, arguments); // 执行主要函数,但是此时的 handler函数的this指向window,也没有事件源对象,apply改变this指向oBtn,传入事件源 arguments[0]
                    lastTime = nowTime;//主要函数执行后, 当前时间就成了过去的时间了。
                }
            }
        }
        // oBtn.onclick = throttle(buy, 1000);
        oBtn.onclick = throttle(buy, 1000);
        function buy(){
            oDiv.innerText = parseInt(oDiv.innerText) + 1;
            //每触发一次,内容 + 1
        }
    </script>
    <script>  // 防抖
        var oInp = document.getElementById("inp");
        function debounce (handler, delay){//第一个参数,主要函数,第二个参数为毫秒
            var timer = null;
            return function (){
                var _self = this, //获取this
                _arg = arguments;//获取事件源对象,(e)
                clearTimeout(timer);
                timer = setTimeout(function(){
                    handler.apply(_self, _arg);//执行主要函数,此时的handler函数this指向window,
                                                //用apply改变this指向和传入事件源对象
                },delay)
            }
        }
        function ajax (e){//模拟ajax
            console.log(this.value);
            console.log(e); //输出到控制台,看看事件源对象 是否为input
        }
        oInp.oninput = debounce(ajax, 1000);//绑定事件
    </script>
</body>
</html>

效果界面如下:
在这里插入图片描述
对于设置了节流的点击函数,在用户疯狂点击按钮时,一秒钟之内只有一次有效点击;对于设置了防抖的搜索框输入,只有当输入稳定一秒种之后才执行控制台打印事件。

注意

可以看到节流与防抖函数都有用到apply()函数,这样做是为了保证设置节流与防抖之后的响应事件内部的this对象的指向和事件源对象与未设置节流防抖之前保持一致。
可以看到节流与防抖函数都使用到了闭包技术来封装定时器变量,这样做可以保护定时器变量不被非法更改。

发布了47 篇原创文章 · 获赞 73 · 访问量 3818

猜你喜欢

转载自blog.csdn.net/whuhewei/article/details/104923111