news 2026/4/18 10:48:19

手写防抖函数

作者头像

张小明

前端开发工程师

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/18 11:05:19

从0到1:我用LLM搭建医学知识库,附详细教程,建议永久收藏

作为一名医学生,作者分享了他使用阿里开源的qwen2.5:7b模型,在本地构建医学知识库的实践经历。他详细描述了从下载模型、处理教材到调试系统的全过程,并强调了AI技术已将创造门槛大幅降低。作者认为,在这个时代,通过动…

作者头像 李华
网站建设 2026/4/18 6:30:25

【年度消费观察】2025,年轻人没有抛弃白酒

文 | 螳螂观察作者 | 风车关于多渠道飞天茅台价格跌破1499元/瓶这事,外界大多将原因归于行业周期调整的大环境因素,或者是禁酒令,或者是消费降级。通俗地讲,当下的产业状态以及酒企集体下行的趋势,支撑不起原有的价格了…

作者头像 李华
网站建设 2026/4/18 8:39:07

【课程设计/毕业设计】基于springboot的校园一卡通管理系统的设计与实现学生身份认证、餐饮消费、缴费管理【附源码、数据库、万字文档】

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

作者头像 李华
网站建设 2026/4/18 10:49:33

精通C++類型系統的工程師:為何他們平均薪資高85%及完整學習路線圖

精通C類型系統的工程師:為何他們平均薪資高85%及完整學習路線圖引言:類型系統的經濟價值在當今軟件工程領域,一個令人矚目的數據值得關注:精通C類型系統的工程師平均薪資比其他工程師高出85%。這個差距不是偶然的,而是…

作者头像 李华