news 2026/5/1 4:14:09

手写防抖函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手写防抖函数

:手写一个防抖函数

答:

/**

* 基础版防抖函数(非立即执行)

* @param {Function} func - 需要防抖的目标函数

* @param {number} delay - 等待时间(毫秒)

* @returns {Function} - 防抖后的函数

*/

function debounce(func, delay) {

let timer = null; // 用闭包存储定时器ID,确保多次调用共享同一个定时器

// 返回防抖后的函数,接收目标函数的参数(...args)

return function (...args) {

// 1. 若已有定时器,先清除(重复触发时重新计时)

if (timer) clearTimeout(timer);

// 2. 重新设置定时器,等待delay后执行目标函数

timer = setTimeout(() => {

func.apply(this, args); // 用apply绑定this(确保目标函数this指向正确)

timer = null; // 执行后清空定时器,避免内存泄漏

}, delay);

};

}

扩展延伸

防抖(Debounce):

核心逻辑:当一个事件会被频繁的触发时,防抖函数不会频繁的执行,而是等待事件停止触发一段时间后才执行;如果在等待执行的过程中,事件再次被触发,则我们需要重新计算需要等待的时间。

典型使用场景:搜索框输入联想(每次按键都会触发输入对应 Input 的事件,我们认为用户结束输入后,我们再进行联想,这个结束输入的判定规则就是,自上一次Input事件触发后的一段时间内,用户没有再触发Input事件,可视为结束输入,需要开始联想),实时输入校验等。

和防抖并列提及的是节流。

节流(Throttle):

核心逻辑:当事件会被频繁触发的时候,节流函数只会按照固定的时间间隔执行,无论期间事件被处罚多少次,都只在每个时间的开头(或结束)执行一次。

典型使用场景:滚动监听(一般用于加载数据判断,每隔一段时间判断一次当前位置,来判断需要加载的数据量),窗口resize事件(用于重新计算布局)

这里简单对比一下防抖和节流:

防抖 节流

执行时机 事件停止触发后,等待一段指定的时间 固定时间间隔执行,每个时间段内仅执行一次

重复触发的问题 重新计算等待的时间,执行会延迟 不影响,固定时间间隔执行

目标 解决冗余的执行 解决过度的执行

使用场景 搜索、校验 滚动加载

搜索输入的过程中,每次键入字符触发搜索,在没有防抖的情况下,仅仅只有最后一次的搜索(即用户输入完成)才是有效的,之前的这些,全部都是没有意义的,只会加重服务负担,即为 “冗余” 。

页面滚动过程中,滚动是持续触发的,在没有节流的情况下,每一次滚动都会有大量的计算过程(假设你的滚动事件是有计算操作的),计算阻塞主线程,会导致页面卡顿,无法正常滚动,即为 “过度” ,如果使用防抖,滚动事件的持续触发,会导致计算一直无法开始,俗称“不跟手”。

面试追问

setTimeout 的延时并不准,有没有办法实现一个更精确的时间检测?

有,使用时间戳 + requestFrameAnimation 实现。

页面滚动加载数据一般用什么?搜索框输入触发联想词,又用什么?

滚动加载一般用节流,防抖需要等用户停止滚动才加载,可能会等很久,节流则是一到底部就加载,可以保证加载的及时性。

搜索联想一般用防抖,因为用户的输入过程会频繁触发联想,但是只有用户停止输入时,触发的联想才是用户想要的、有效的。

我看你在防抖函数中,用了 apply 这是为啥?为啥不可以直接用 func ?

主要是 this 指针的指向问题,防抖函数返回的是一个新的函数,假设现在设置的是 input.oninput = debounceSearch,这个 debounceSearch 中如果有 this,那么预期是要指向 input 标签,但是我们直接调用 func 的话,this 会指向 window 或 undefined,和预期不一致。

防抖函数中,如果目标函数有返回值,我们可以拿到吗?

不行,即使返回目标函数结果也不行,因为他在 setTimeout 里面执行的,无法返回对应的执行结果。

但是我就需要这个返回结果,有没有办法?

有,两种办法,一是将 setTimout 用 Promise 封装起来,setTimeout 的回调执行时,resolve 这个 Promise 就可以了,这样防抖函数就变成了一个异步的api,二是使用回调参数,在目标函数执行后,调用这个回调就可以了。

有没有遇到过防抖函数导致内存泄漏的情况?

没有,但是防抖函数有内存泄漏的可能性,本质上是闭包写法产生的,编写代码的时候注意闭包的处理就可以了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 0:56:22

【毕业设计】基于springboot的村务管理系统的设计与实现基于SpringBoot的村事务处理平台的设计与实现(源码+文档+远程调试,全bao定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/4/23 10:59:09

达梦数据库深度实践与学习心得

好的,以下是一篇关于达梦数据库深度实践与学习心得的文章,包含文字、代码示例和详细目录,内容力求丰富实用:达梦数据库深度实践与学习心得作者:XXX 字数:约3000字目录引言1.1 国产数据库的发展背景1.2 达梦…

作者头像 李华