什么是防抖和节流?有什么区别?如何实现?
JavaScript 中防抖和节流的概念
定义
防抖(Debounce)是指当某个事件被触发后,在设定的时间内如果没有再次触发该事件,则执行相应的操作;如果在这段时间内又触发了该事件,则重新计时。
节流(Throttle)则是指在一定时间内只允许某件事情发生一次或者几次,通常用于控制高频事件的触发频率。
区别
特性 | 防抖 | 节流 |
---|---|---|
核心概念 | 延迟一段时间后再执行回调函数,期间多次触发会重置定时器 | 在固定时间段内最多执行一次回调 |
适用场景 | 用户输入完成后的延迟处理(如搜索框自动补全)、窗口调整完成后触发某些逻辑 | 按钮点击、滚动条监控等需要限制调用次数的场景 |
触发时机 | 只有最后一次触发才会生效 | 时间段内的第一次或指定周期触发 |
实现方法
防抖实现
以下是基于 setTimeout
的简单防抖函数实现:
function debounce(func, delay) {let timer;return function (...args) {clearTimeout(timer);timer = setTimeout(() => func.apply(this, args), delay);};
}
此代码片段中,每次调用返回的新函数都会清除之前的定时器,并设置一个新的定时器。
节流实现
以下是基于时间戳的节流函数实现:
function throttle(func, limit) {let lastFunc;let lastRan;return function () {const context = this;const args = arguments;if (!lastRan) {func.apply(context, args);lastRan = Date.now();}else {clearTimeout(lastFunc);lastFunc = setTimeout(function () {if ((Date.now() - lastRan) >= limit) {func.apply(context, args);lastRan = Date.now();}}, limit - (Date.now() - lastRan));}};
}
在此代码中,只有当前时间和上次运行时间之间的差值大于等于设定的阈值时才执行函数。
示例代码对比
防抖示例
假设有一个按钮点击事件,我们希望用户停止连续点击一秒之后再执行相应动作:
<button id="debounceBtn">Click Me</button>
<script>const button = document.getElementById('debounceBtn');function handleClick() {console.log('Button clicked!');}button.addEventListener('click', debounce(handleClick, 1000)); // 设置防抖时间为1秒
</script>
节流示例
对于鼠标滚轮事件,我们可以限制每秒钟最多触发一次:
<div style="height: 200vh;">Scroll me!</div>
<script>window.addEventListener('scroll', throttle(() => {console.log('Scrolled!');}, 1000)); // 设置节流时间为1秒
</script>
对比表格
属性 | 防抖 | 节流 |
---|---|---|
目标 | 确保事件结束后的一段时间内仅执行一次 | 控制单位时间内某一事件的最大执行次数 |
典型应用场景 | 文本输入框中的实时查询、浏览器窗口大小改变 | 页面无限加载、拖拽过程中计算位置 |
性能影响 | 更适合减少不必要的重复请求 | 更适合降低高频率事件对系统的压力 |
首次触发行为 | 不立即响应 | 立即响应 |
最终触发行为 | 如果持续触发不会被执行 | 即使持续触发也会按设定间隔执行 |
栗子总结