手写防抖函数debounce

多年前,你是否经历过这种骗局:当电脑进度条龟速前进甚至卡死的时候,有没有人教你只要你狂按enter,电脑响应就会变快。

多多少少受这个谣言的影响,部分人现在点个确认提交1s内能狂点10下,如果所有用户都这样,1s对服务器发起十几甚至几十次请求,不仅服务器得崩,没准一气之下,把电脑也砸了(手动狗头)。

因此,有了防抖和节流这两种解决办法,本文先介绍防抖,典型应用场景有以下几种:

  1. scroll事件滚动触发;
  2. 搜索框输入查询
  3. 表单验证
  4. 按钮提交
  5. 浏览器的窗口缩放,resize事件

于是我跟着可爱的马勾勾老师,一起走了一遍防抖代码,看其内部实现机制,源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #div1{
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            background-color: pink;
            color: grey;
        }
        #div2{
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            background-color: lightcoral;
            color: #ffffff;
        }
    </style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
<button>关闭防抖</button>
<script>
    function debounce(fn,wait,immediate){   //参数意义:想要限制次数的事件,延时时长,等待/立即执行
        let timer, result;     //timer定时器,result接受fn可能存在的返回值
        // console.log(this);  //优化前是window
        let debounced = function(){
            // console.log(this);  //优化前是odiv
            // console.log(arguments);
            let _ = this;   // 使函数调用时的this指向事件发生对象
            let args = arguments;   // 使函数调用时的event指向事件发生对象
            clearTimeout(timer);    // wait时间内再次触发时间,从新开始计时
            if(immediate){
                // 鼠标移动立即执行
                // 初次timer为空,fn能立即执行,否则会等待wait时间才能再次立即触发
                let now = !timer;   
                timer = setTimeout(()=>{
                    timer = null;
                },wait);
                if(now) result = fn.apply(_, args);
            }
            else{
                // 第一次不会立即执行,等待wait时间后执行第一次
                timer = setTimeout(function () {
                    result = fn.apply(_, args);
                }, wait);
            }
            return result;
        };
        // 取消防抖事件
        debounced.cancel = function(){
            clearTimeout(timer);    //清空定时器
            timer = null;           //释放定时器(存在闭包)
        };
        return debounced;
    }


    let count = 0;
    let num = 0;
    let odiv1 = document.querySelector('#div1');
    let odiv2 = document.querySelector('#div2');
    let obtn = document.querySelector('button');

    function doSomething(ev){
        // console.log(ev);  //优化前是undefined
        odiv1.innerHTML = count++;
        // console.log(this);  //odiv
    }
    setInterval(function () {
        odiv2.innerHTML = num++;
    },1000);
    let dosome = debounce(doSomething, 5000);
    obtn.onclick = function () {
        dosome.cancel();
    };
    odiv1.onmousemove = dosome;
</script>
</body>
</html>

原视频链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值