防抖函数中的this和闭包

前言

最近我们学习了闭包,this,对象,作用域的一些基本知识,今天蘑菇头就来分享一个案例,将这些知识都串联起来。一起来看看你还记得多少。

防抖

今天蘑菇头要聊的案例叫做防抖,那么什么是防抖呢?在前端开发中,防抖(Debounce)是一种常用的优化技术。它主要用于处理频繁触发的事件(如滚动、输入等)。其基本原理是,在事件触发后,延迟一段时间再执行相关的操作,如果在这段延迟时间内又有新的事件触发,则重新开始计时,直到延迟时间结束且没有新的事件触发才真正执行操作。这样可以避免因为频繁触发事件而导致不必要的大量计算或请求,提高性能和用户体验。我们用一个小demo来实现一下防抖。

案例

我们写一个按钮,当点击这个按钮一下就打印一句话用来模拟发请求这个动作。

当我们一直点击提交这个按钮时,他会一直发送请求到我们的后台服务器,这些请求都是同一个请求,后台服务器有可能会因为承受不住这样的压力而奔溃,所以我们需要设计一个方法,当用户一直连续点击提交时,不发送请求到后端,而是停止点击后发送请求,这样就能给我们后台服务器减轻压力,实现优化。

思路历程

  1. 首先我们获取到提交按钮,给他添加点击事件监听,当点击时,发送请求。
javascript 复制代码
let btn = document.getElementById('btn');
btn.addEventListener('click', function(){
     handle();
});         
//模拟请求
function handle() {
      console.log('人生无常,大肠包小肠');
}
  1. 我们知道有一个函数叫做setTimeout,他的作用是当过完设定好的时间之后执行回调函数。那么我们可以试着将请求放进回调函数里,看看能不能行。
javascript 复制代码
btn.addEventListener('click', function(){
     setTimeout(function(){
         handle();
     },1000)
}); 

可以发现,当我们一直连续点击时,他会等一段时间后疯狂打印,这显然不是我们想要的效果,我们想要的是当一直连续点击后发送一个请求,也就是打印一句话。

  1. 继续优化,设计一个防抖函数出来
javascript 复制代码
btn.addEventListener('click', debence(handle));
//模拟请求
function handle() {
      console.log('人生无常,大肠包小肠');
}
//防抖函数
function debence(handle){
    let timer = null;
    return function (e) {
    //如果第二次的时间没到1秒,就销毁上一个定时器
    // 第二次点击时,会找到上一次闭包中的timer,并且销毁
    clearTimeout(timer)
    timer = setTimeout(()=>{
          handle.call(this,e);
         }, 1000);
    }
}

我们利用闭包的原理,内部函数一定可以访问外部函数的变量,当内部函数被拿到外部函数之外调用时,即使外部函数执行完毕,但是内部函数对外部函数中的变量依然存在引用,那么这些被引用的变量会以一个集合的方式保存下来。我们设计一个timer将定时器保存下来,当第二次点击在规定的时间内时,由于第一次点击的事件还未结束,并且timer被闭包保存下来了,所以第二次点击时他会去找闭包中的timer销毁,这样第一次点击创建的定时器以及里面的请求就会被销毁,然后会创建一个新的timer,这样定时器倒计时间就完成更新了。

问题

  1. this指向问题

    注意,此时的handle的this是指向全局的,并不是指向dom结构的,所以我们需要更改this的指向,使用显示绑定规则,handle.call(this),这个this是谁有必要说明一下,箭头函数没有this,所以去上一级找,不是定时器的this,而是这个return函数的this,也就是debence(handle)的this,它是指向dom结构的,我们需要同步handle的this到dom结构上。

  2. 事件参数e的问题

    我们需要将事件参数e给到handle函数,所以还需在return函数传参,并且给到handle,这样我们的handle才能拿到事件参数。

总结

今天我们学习了什么是防抖以及如何手搓一个简单的防抖函数,并且里面还有一些注意事项需要了解。

相关推荐
在未来等你9 小时前
Elasticsearch面试精讲 Day 9:复合查询与过滤器优化
大数据·分布式·elasticsearch·搜索引擎·面试
零千叶9 小时前
【面试】AI大模型应用原理面试题
java·设计模式·面试
F2E_Zhangmo11 小时前
基于cornerstone3D的dicom影像浏览器 第三章 拖拽seriesItem至displayer上显示第一张dicom
前端·javascript·cornerstone·cornerstone3d·cornerstonejs
boonya13 小时前
Elasticsearch核心原理与面试总结
大数据·elasticsearch·面试
gnip16 小时前
Jst执行上下文栈和变量对象
前端·javascript
excel16 小时前
🐣 最简单的卷积与激活函数指南(带示例)
前端
醉方休17 小时前
npm/pnpm软链接的优点和使用场景
前端·npm·node.js
拉不动的猪17 小时前
简单回顾下Weakmap在vue中为何不能去作为循环数据源,以及替代方案
前端·javascript·vue.js
How_doyou_do17 小时前
数据传输优化-异步不阻塞处理增强首屏体验
开发语言·前端·javascript
奇舞精选17 小时前
超越Siri的耳朵:ASR与Whisper零代码部署实战指南
前端·人工智能·aigc