防抖的核心思想是:在事件触发后,先等待一段时间,如果在这段时间内没有再次触发事件,则执行回调;如果在这段时间内时间又被触发,则重新计时。
应用场景
- 输入框实时搜索(等待用户输入完成后再发送请求)。
- 窗口大小调整(等待用户停止调整后再计算布局)。
手写实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | function debounce(func, delay) {let timer = null;
 
 return function (...args) {
 const context = this;
 
 
 if (timer) {
 clearTimeout(timer);
 }
 
 
 timer = setTimeout(() => {
 func.apply(context, args);
 }, delay);
 };
 }
 
 | 
3. 进阶:支持立即执行的防抖
有时候我们需要在事件触发时立即执行一次函数,然后再进入防抖模式。以下是支持立即执行的防抖实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | function debounce(func, delay, immediate = false) {let timer = null;
 
 return function (...args) {
 const context = this;
 
 
 if (timer) {
 clearTimeout(timer);
 }
 
 
 if (immediate && !timer) {
 func.apply(context, args);
 }
 
 
 timer = setTimeout(() => {
 timer = null;
 if (!immediate) {
 func.apply(context, args);
 }
 }, delay);
 };
 }
 
 | 
4. 进阶:支持取消的防抖
有时候我们需要在特定条件下取消防抖或节流的执行。以下是支持取消的实现:
防抖(支持取消)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | function debounce(func, delay) {let timer = null;
 
 const debounced = function (...args) {
 const context = this;
 
 if (timer) {
 clearTimeout(timer);
 }
 
 timer = setTimeout(() => {
 func.apply(context, args);
 }, delay);
 };
 
 
 debounced.cancel = function () {
 if (timer) {
 clearTimeout(timer);
 timer = null;
 }
 };
 
 return debounced;
 }
 
 | 
使用建议
通过手写,可以更好地理解它们的原理和应用场景。在实际开发中,请直接使用 Lodash 等工具库提供的 debounce 方法。
| 1
 | _.debounce(func, [wait=0], [options=])
 |