前言
此篇以记录我个人对JS开发中防抖与节流的见解,欢迎大家在评论区交流,有错误的地方也希望大家能开金口指正
1.防抖与节流是什么
在JavaScript中,防抖(Debouncing)和节流(Throttling)是两种常用于优化函数执行的技术,特别是在处理频繁触发的事件(如窗口调整大小、滚动、按键等)时非常有用
防抖:
防抖技术的核心思想是:在事件被频繁触发的情况下,延迟函数的执行,直到最后一次事件触发后经过了指定的时间间隔没有再次触发事件,才执行函数。
通俗地来讲:就像MOBA游戏里的回城,按了回城之后,如果角色动了,回城的倒计时就会被重置,只有角色不动的时间与回城等待时间一样时,我们才能触发功能
节流:
节流技术的核心思想是:在事件被频繁触发的情况下,保证函数在指定的时间间隔内最多只执行一次,不管事件触发了多少次。
通俗的来讲:就像MOBA游戏里的技能冷却,CD没到按多少次都不会触发机制,只有CD到了才能触发指定功能
2.防抖与节流出现是为了解决什么问题
防抖(Debouncing)和节流(Throttling)技术的出现是为了解决JavaScript中由于事件频繁触发而导致的性能问题,具体包括:
-
性能优化:
- 在JavaScript中,某些事件(如窗口调整大小、滚动、按键等)可以非常频繁地触发。如果每次事件触发都执行一个耗时的操作,这将极大地影响页面的性能。防抖和节流通过限制这些操作的执行频率,帮助提高性能。
-
减少不必要的计算:
- 有些操作可能需要进行复杂的计算或数据处理,如果这些操作因为频繁的事件触发而被反复执行,将是一种资源浪费。通过防抖和节流,可以减少这些不必要的计算。
-
避免界面卡顿:
- 如果一个事件处理函数执行时间过长,可能会导致浏览器的渲染进程被阻塞,从而造成界面卡顿或无响应。防抖和节流可以确保事件处理函数不会过于频繁地执行,避免这种情况的发生。
-
改善用户体验:
- 用户体验很大程度上取决于应用的响应速度和平滑性。防抖和节流通过优化事件处理,确保用户界面能够流畅地响应用户的操作。
-
网络请求优化:
- 在处理如搜索建议、实时过滤等功能时,如果不加限制地发送大量请求到服务器,可能会导致服务器过载,同时也会增加网络延迟。防抖可以确保在用户完成输入后只发送一次请求,而节流可以控制请求发送的频率。
-
资源利用效率:
- 在处理大量数据或进行复杂操作时,合理地调度资源的使用可以提高效率。防抖和节流可以帮助开发者更有效地管理CPU和内存等资源的使用。
-
防止抖动:
- 在处理用户输入或其他动态数据时,有时数据可能会在短时间内频繁变动。防抖技术可以确保只有在数据稳定一段时间后才进行处理,从而避免因为数据的微小变动而反复执行操作。
总而言之,就是提高程序的性能,通过这些技术,开发者可以构建出更加健壮和高效的Web应用,提供更好的用户体验。
3.防抖与节流为何有效?
防抖和节流之所以有效,是因为它们通过控制函数的执行,解决了由于事件频繁触发导致的性能问题和资源浪费。它们使得开发者可以根据实际需要,优化事件处理逻辑,提高应用的响应速度和稳定性,从而提供更好的用户体验。
4.防抖与节流如何实现
防抖:
// 创建一个防抖函数
function debounce(fn, wait) {
// 使用let关键字定义的timeout变量具有块级作用域,避免多次调用时的冲突
let timeout;
// 返回一个新的函数,这个函数将在每次事件发生后被调用
return function() {
// 保存this上下文和参数
const context = this;
const args = arguments;
// 每次事件触发时,清除之前的定时器
clearTimeout(timeout);
// 设置一个新的定时器,当超过指定的时间间隔后执行传入的函数fn
timeout = setTimeout(() => {
fn.apply(context, args);
}, wait);
};
}
调用:
// 使用节流函数包装实际要执行的函数
window.addEventListener('scroll', throttle(function() {
console.log('滚动事件');
}, 1000)); // 每1000毫秒内,无论触发多少次滚动事件,都只执行一次函数
这里比较难懂的是this的指向,使用.apply()的目的是使每每次回调函数的this指向正确,使函数具有复用性
节流:
function throttle(fn, limit) {
let inThrottle;
return function() {
const context = this;
const args = arguments;
if (!inThrottle) {
fn.apply(context, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
调用:
window.addEventListener('scroll', throttle(function() {
console.log('滚动事件');
}, 1000));
原理与防抖基本一致,在这里就不多赘述