函数防抖

什么是函数防抖

有一些函数, 会出现短时间内高频调用的情况, 比如调整窗口大小, 然后页面的布局随着修改, 实现新的布局.

生活中的例子就是, 人上电梯, 电梯不会立马开始关门操作, 而是等待两秒, 如果两秒有人进来了, 就继续等, 没了才会执行关闭电梯的方法.

这种情况下, 如果一个函数调用的频率过高, 就会产生性能问题. 为了解决这些问题, 我们就需要实现函数防抖.

函数防抖的三个条件

并不是所有的函数都需要防抖, 函数防抖是有三个条件的:

  1. 高频函数
  2. 耗时函数
  3. 以最后一次调用为准

例如, 重新绘制窗口, 我们只以最后一次渲染为基准.

实现防抖代码

其实要做的就是实现一个等待, 没有了再进行就好. 可以先声明一个 timerID, 记录计时器, 如果有人进电梯, 就清空计时器, 重新开始即可.

1
2
3
4
5
6
7
8
9
10
11
// 例如 我有一个当窗口重新改变大小才会运行的内容

// 定义一个记录ID的东西
let timerID;

window.onresize = () => {
clearTimeout(timerID);
timerID = setTimeout(() => {
console.log("窗口大小重新设置", window.innerWidth, window.innerHeight);
}, 1000);
};

现在就可以看到, 只有一定时间后, 函数才会被调用了.

抽离防抖代码

我们知道原理了, 那么就可以开始实现了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 根据原函数, 生成防抖函数
* @param {Function} func 需要进行防抖的函数
* @param {number} duration 防抖时间
* @returns 防抖处理过的函数
*/
function debounce(func, duration = 500) {
// 这里为了保留this指向, 使用function而不是箭头函数
let timerId;
// 这里也是保留this指向
return function (...args) {
clearTimeout(timerId);
// 这里使用箭头 保留外部的this, 能够传递到内部
timerId = setTimeout(() => {
func.apply(this, args);
}, duration);
};
}

// 获取一个防抖函数
const d_resize = debounce(() => {
console.log("窗口大小重置了");
});

window.onresize = d_resize;

正常使用, 并且考虑到了各种情况.

提示: 我们不一定需要背代码, 理解其中的原理才是关键.