防抖和节流-‘帕金森’网友的良方

前言

各位掘友们平时都没少上网噜,在冲浪的时候没少遇到过网络卡顿的情况,每当点击链接或者图片没有反应的时候,就会烦躁地一通乱点,那么掘友们有没有想过在你的一番操作之下,这个程序究竟在背地里运行了多少次?一次?好多次?好好好,今天我们就要来聊聊点点点的那些事。

防抖

掘友们从名字就能看出点门道来。防抖------就是防止 '帕金森' 网友的手抖。防抖是指在一定时间内,如果事件被频繁触发,只执行最后一次事件。可以用于优化一些高频率触发的事件,比如窗口大小改变,滚动事件等。也就是说当网友点击一个提交按钮后1s后进行提交,但是网友在1s内重复点击,那么就从最后一次点击开始计算1s后进行提交。

那么我们要如何实现这个效果呢?我们一起来看看:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<button id="btn">提交</button>
    <script> 
        function send(e){
            console.log(this,'提交完成',e);
        }
        let btn = document.getElementById('btn')
        btn.addEventListener('click',debounce(send,1000))
        function debounce(fn,delay){
            let timer;
            return function(){
                let args = arguments
                if(timer) clearTimeout(timer)
                timer= setTimeout(() => {
                    fn.call(this,...args)
                },delay)
            } 
        }
    </script>
</body>
</html>

首先我们设置了一个button用来模拟点击提交事件。接下来,为了监听按钮我们得在按钮上设置一个监听器。点击按钮以后,我们就运行debounce()

js 复制代码
 function debounce(fn,delay){
            let timer;
            return function(){
                let args = arguments
                if(timer) clearTimeout(timer)
                timer= setTimeout(() => {
                    fn.call(this,...args)
                },delay)
            } 
        }

debounce()中传入了两个参数,fndelayfn 是一个函数,也就是我们要进行的各种操作,也就是点击按钮后的一些操作,delay 就是我们设置的延迟时间。在函数体内,我们先声明了一个timer ,用来记录我们的计时器,如果在之前点击了按钮,那么timer 就不为空,当再次点击按钮时,判断timer 不为空,于是调用clearTimeout()方法,将定时器重置,实现在一定时间内只执行最后一次操作的效果。

细心的掘友会发现,如果我的send()方法中传入多个参数,那么怎么办呢?我们可以看到,在函数体内调用fn()方法的时候使用了解构,让fn()传入的实参解构再调用,那么无论fn()中有多少个形参,都能使用防抖。(不了解解构的掘友们请移步"跃迁ES6:探索JavaScript语言的最新进展(一)")

在这个防抖函数的实现中,fn 函数是通过 call() 方法调用的。具体来说,fn.call(this, ...args) 的作用是:将 fn 函数中的 this 指向当前上下文中的 this(也就是防抖函数返回的新函数的执行环境),并将传入的 args 参数展开后作为参数传递给 fn 函数。

节流

好好好,刚才我们从防抖的名字就能看出点门道来,那么这节流又是一个啥玩意?节流(throttle)指的是在一定时间间隔内只执行一次函数,用于优化高频率触发的事件,比如 scrollresizemousemove 等。与防抖不同的是,节流函数会按照固定的时间间隔执行函数,而不是在等待一段时间后才执行。

我们话不多说,先上代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id = "btn">提交</button>
</body>
<script>
    function send(){
        console.log('提交完成');
    }
    let btn = document.getElementById('btn')
    btn.addEventListener('click',throttle(send,1000))
    function throttle(fn,delay){
        let prevTime = Date.now()
        return function(){
           if(Date.now()-prevTime>delay){
             fn.apply(this,arguments)
             prevTime = Date.now()
           }
        }
    }
</script>
</html>

同样的我们看到throttle()方法

js 复制代码
function throttle(fn,delay){
        let prevTime = Date.now()
        return function(){
           if(Date.now()-prevTime>delay){
             fn.apply(this,arguments)
             prevTime = Date.now()
           }
        }
    }

与防抖方法不一样的地方是,不管我们在delay 这段时间内点击了多少次,我们只在 delay 时间过去后调用一次fn 方法。那么我们是如何记录时间的呢?这里使用到了Date.now(),这个方法返回的是现在距离1970年经过的毫秒数,储存在prevTime 变量中,如果后面的点击时间距离第一次点击时间大于delay 则运行 fn ,掘友们要注意的是,在运行以后,要将prevTime的时间进行更新,这样才能保证下一次点击事件的正确运行。

结尾

在实际开发中,合理地运用节流和防抖可以减少不必要的函数执行,降低资源消耗,提升页面响应速度。无论是处理 DOM 事件、AJAX 请求还是其他异步操作,都可以考虑使用节流和防抖来优化程序性能。希望本文对你有所帮助,也欢迎读者在实际项目中尝试运用这两种技巧,从而改善用户体验,提升应用性能。"

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax