防抖和节流

节流与防抖:前端性能优化的利器

在前端开发中,我们经常会遇到需要处理高频触发事件的情况,比如窗口滚动、页面缩放、输入框内容变化等。如果不加以限制,这些事件的处理函数可能会被频繁调用,导致性能问题。节流和防抖是两种常用的优化技术,能够有效减少函数的执行次数,提高程序的性能。

一、节流(Throttle)

概念

节流是指在一定的时间间隔内,函数只被调用一次。如果在这个时间间隔内触发了多次事件,只有第一次会调用函数,其余的会被忽略,直到时间间隔过去,重新开始计时。

实现原理

节流的实现思路是:每次事件被触发时,如果函数没有在指定的时间间隔内被调用过,则调用函数并设置一个计时器,在指定的时间间隔内不再触发事件。如果在指定的时间间隔内再次触发了事件,则不调用函数,直到指定的时间间隔过去,重新开始调用函数。

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(fn, delay) {
let timer = null;
return function() {
const context = this;
const args = arguments;
if (!timer) {
timer = setTimeout(function() {
fn.apply(context, args);
timer = null;
}, delay);
}
};
}

使用场景

  • 页面滚动事件:在处理滚动事件时,我们可能需要监听页面的滚动位置来执行某些操作,比如懒加载图片。如果每次滚动都执行函数,会导致性能问题。使用节流可以限制函数的执行频率。
  • 窗口大小调整事件:当用户调整窗口大小时,可能需要重新布局页面元素。使用节流可以避免函数被频繁调用。

二、防抖(Debounce)

概念

防抖是指等待指定的时间,并且指定时间内无再次调用,才执行一次函数。如果在这段时间内调用了,就重新计时,再等到指定时间内无调用时执行函数。

实现原理

防抖的原理是利用函数的闭包特性,将函数和等待时间封装在一起,形成一个防抖函数。当事件或函数调用被触发时,防抖函数会检查是否已经过了等待时间,如果过了等待时间,则执行处理函数;如果没有过等待时间,则重新计时并等待。

实现代码

1
2
3
4
5
6
7
8
9
10
11
function debounce(fn, delay) {
let timer = null;
return function() {
const context = this;
const args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}

使用场景

  • 输入框联想搜索:在搜索框中输入内容时,我们希望在用户停止输入一段时间后再发送请求获取联想建议,而不是每次输入都发送请求。使用防抖可以实现这一需求。
  • 窗口大小调整后的布局调整:在窗口大小调整完成后,再执行布局调整的代码,避免在调整过程中频繁执行。

三、节流与防抖的区别

节流和防抖都是用于优化事件或函数调用频率的技术,但它们的工作原理和应用场景有所不同。节流更注重限制执行频率,而防抖则更注重减少处理函数的调用次数。

  • 节流在一定时间间隔内只执行一次函数,适合于需要定期执行的场景,如滚动事件。
  • 防抖在事件停止触发后才执行函数,适合于需要等待用户操作完成的场景,如输入框搜索。

四、总结

在实际开发中,根据具体需求选择合适的优化策略非常重要。如果需要在高频事件中定期执行某些操作,节流是一个不错的选择;如果希望在用户操作结束后再执行函数,防抖则更为合适。合理使用这两种技术,可以有效提升前端应用的性能和响应速度。

实际上也有已经封装好的函数,lodash直接引用js文件也是可以的。