【连载】手摸手解析JS手写面试题题系列1——实现debounce(防抖)方法

简介: 手摸手解析JS手写面试题题系列1——实现debounce(防抖)方法

手摸手解析JS手写面试题题系列1——实现debounce(防抖)方法

关注程序员耳东,编程转码真轻松

这是手摸手解析JS手写面试题系列第1篇,聊聊如何实现debounce(防抖)方法

啥是debounce(防抖)

首先说说啥是debounce, 这个单词中文名就是防抖,之前没接触过的人可能一脸蒙

不过没关系我最擅长的就是通俗易懂的解释清楚概念,我一说你就明白了

举个例子,比如说这样一个场景:

比如下图这样,用户在输入框里面输入字符,然后根据用户输入的字符去后端模糊查询,这是个很常见的场景对吧?这就是经常说到的联想搜索

OK,我们继续探究这个功能的细节

比如你想搜索“世界杯”这三个字,普通的联想输入框是这样运作的:

  1. 在你敲入第一个字的时候,触发了输入框的onchange事件,前端带着“世”这个字向后端发起1次请求
  2. 在你敲入第二个字的时候,触发了输入框的onchange事件,前端带着“世界”这两个字向后端发起1次请求
  3. 在你敲入第三个字的时候,触发了输入框的onchange事件,前端带着“世界杯”这三个字向后端发起1次请求

你品一品,用户飞速的敲完3个字,前端居然发起了3次请求,这合理吗?难道我们不是只需要第3次请求就够了吗?

能不能有一个办法可以让用户停止输入的时候才执行发请求的方法,避免用户在快速输入的时候连续的发请求?

答案就是debounce方法,它可以让某个方法在快速连续被激发的时候不会执行,可以保障用户在输入完毕时才去真正的执行方法

接下来,我们一步一步用代码实现debounce方法

跟我一步一步代码实现debounce(防抖)

写测试的例子

在开始写debounce之前,我们先把验证的代码写好,这样子就可以保证我们写一点代码就可以验证一点代码

记住一点就是,很少有人可以一次性就写出最佳的代码,大部分都是先写个最简单最糙的版本然后一点一点的优化出来的

验证的代码我们就以前面说到的输入框为例,写一个方法来响应input的onChang事件,假装发起了请求,来显示onChang事件的响应频率 测试代码如下:

<body>
    <input id="debounce-input" placeholder="防抖输入框" />
    <script>
        const input = document.getElementById('debounce-input');
        const handleInputOnChange = (e) => {
            console.log(e);
            console.log('发起请求...');
        }

        input.oninput = handleInputOnChange;
    </script>
</body> 

先思考伪代码

我们写一个代码之前呢,先要把它想清楚,只要你想顺了,那代码写的就很顺了,在思考代码逻辑的过程中可以使用伪代码来辅助

什么是伪代码,就是我们使用人话来把我们想要实现的代码过程和步骤讲一遍

OK,思考debounce伪代码之前先看看它是怎么用的

const handleInputOnChangeDebounced = debounce(handleInputOnChange, 300);
input.oninput = handleInputOnChangeDebounced;

这段代码的意思就是我们使用debounce方法把handleInputOnChange方法包装一下,并且返回一个新的方法handleInputOnChangeDebounced

这个handleInputOnChangeDebounced方法响应输入框的输入事件,在用户以非常快的速度(两次输入的间隔时间小于300毫秒)输入的时候,不会去执行handleInputOnChange方法,只有在用户两次输入间隔大于300毫秒才会执行handleInputOnChange方法

这里有个细节需要注意,什么情况下用户两次输入间隔会小于300毫秒,有两种情况:

  1. 用户打字的手速比较慢,两次输入的间隔大于了300毫秒,此时因为用户手速实在是太慢了,我们不需要很刻意的去做debounce,所以每次输入后都会执行一次handleInputOnChange
  2. 用户手速很快的打完了一段文字并且停止了输入,此时最后一次输入完毕后过300毫秒就会执行handleInputOnChange

再开始写代码

OK,我们接下来写代码

首先实现一个最基础的debounce方法的架子:

function debounce(func, wait) {
    return function (...args) {
        // 代码
    }
}

debounce方法接收两个参数func和wait,func是被包装的方法,wait是用户两次输入间隔大于多少时会执行func

接下来问题的难点就是如何实现:用户两次输入间隔大于wait时才执行func,否则就不执行func

这个问题其实可以从这个角度来思考:

我们可以借助定时器setTimeout来做,声明一个定时器来在wait时间后执行func

如果用户输入的很慢(两次输入间隔大于了wait)或者输入结束,那这个setTimeout就顺利了执行了func;

如果用户输入的很快(两次输入间隔小于了wait),那我们取消当前这个setTimeout再重新生成一个新的setTimeout去延时执行func即可;

这样子我们就巧妙的使用了定时器的延时来控制函数的响应,延时范围内的就新生成一个定时器,延时范围外的就让它执行好了,也该它执行了

代码如下:

function debounce(func, wait) {
    let timerId = 0;
    return function (...args) {
        if (timerId) {
            clearTimeout(timerId);
        }
        timerId = setTimeout(() => {
            func.apply(this, args);
        }, wait);
    }
}

这里面的细节我说一下,防止有的人看不太明白

变量timerId放在返回的方法外面,用来记录当前的那个定时器,并且timerId会在返回的方法内部使用到,这不就是妥妥的闭包吗?之前学习到的知识瞬间就用到了

然后返回的方法内部有一个if判断,就是如果当前有个定时器,别管这个定时器是否执行,先取消了再说,因为如果它执行了,那我clear它也不会有什么影响,如果它没执行,那刚好说明它还在wait这个时间间隔内,正好取消掉它

取消掉当前的定时器之后,再新生成一个定时器来延时执行func

定时器内部执行func的时候,需要把方法接收的参数都透传给func,并要保留住this

验证

验证代码就很简单了,如下:

<body>
    <input id="debounce-input" placeholder="防抖输入框" />
    <script>
        const input = document.getElementById('debounce-input');
        const handleInputOnChange = (e) => {
            console.log('发起请求...');
        }

        input.oninput = debounce(handleInputOnChange, 300);
    </script>
</body>

总结

这是手摸手解析JS手写面试题的第1篇,实现debounce方法是一个非常常见并且非常锻炼javascript能力的过程,在这个过程中练习到了闭包、定时器、抽象思维等等能力

希望对你们有帮助,有问题欢迎讨论

相关文章
|
5月前
|
人工智能 前端开发 Java
Java 面试资料中相关代码使用方法与组件封装方法解析
这是一份详尽的Java面试资料代码指南,涵盖使用方法与组件封装技巧。内容包括环境准备(JDK 8+、Maven/Gradle)、核心类示例(问题管理、学习进度跟踪)、Web应用部署(Spring Boot、前端框架)、单元测试及API封装。通过问题库管理、数据访问组件、学习进度服务和REST接口等模块化设计,帮助开发者高效组织与复用功能,同时支持扩展如用户认证、AI推荐等功能。适用于Java核心技术学习与面试备考,提升编程与设计能力。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
139 6
Java 面试资料中相关代码使用方法与组件封装方法解析
|
10月前
|
监控 安全 网络安全
深入解析PDCERF:网络安全应急响应的六阶段方法
PDCERF是网络安全应急响应的六阶段方法,涵盖准备、检测、抑制、根除、恢复和跟进。本文详细解析各阶段目标与操作步骤,并附图例,助读者理解与应用,提升组织应对安全事件的能力。
1473 89
|
11月前
|
存储 Java 开发者
浅析JVM方法解析、创建和链接
上一篇文章《你知道Java类是如何被加载的吗?》分析了HotSpot是如何加载Java类的,本文再来分析下Hotspot又是如何解析、创建和链接类方法的。
521 132
|
7月前
|
人工智能 算法 数据库
美团面试:LLM大模型存在哪些问题?RAG 优化有哪些方法?_
美团面试:LLM大模型存在哪些问题?RAG 优化有哪些方法?_
|
9月前
|
自然语言处理 JavaScript 前端开发
当面试官再问我JS闭包时,我能答出来的都在这里了。
闭包(Closure)是前端面试中的高频考点,广泛应用于函数式编程中。它不仅指函数内部定义的函数,还涉及内存管理、作用域链和垃圾回收机制。闭包可以让函数访问其外部作用域的变量,但也可能引发内存泄漏等问题。通过合理使用闭包,可以实现模块化、高阶函数和回调函数等应用场景。然而,滥用闭包可能导致代码复杂度增加、调试困难以及潜在的性能问题。为了避免这些问题,开发时应谨慎处理闭包,避免不必要的嵌套,并及时清理不再使用的变量和监听器。
408 16
当面试官再问我JS闭包时,我能答出来的都在这里了。
|
9月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
618 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
8月前
|
JSON 监控 网络协议
Bilibili直播信息流:连接方法与数据解析
本文详细介绍了自行实现B站直播WebSocket连接的完整流程。解析了基于WebSocket的应用层协议结构,涵盖认证包构建、心跳机制维护及数据包解析步骤,为开发者定制直播数据监控提供了完整技术方案。
|
8月前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
255 1
|
8月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
339 5

推荐镜像

更多
  • DNS