# 防抖函数&节流函数

节流函数和防抖函数是 JS 比较重要的概念,应用好了可以提高很大的性能,在面试中也是很高频的一个考点。下面一起来看看这两种方法是如何使用的:

# 防抖函数(debounce):

# 概念:

在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时

# 生活中的栗子:

如果有人进电梯(触发事件),那电梯将在 10 秒钟后出发(执行事件),这时如果又有人进电梯了(在 10 秒内再次触发该事件),我们又得等 10 秒再出发(重新计时)。

# 代码栗子:

/**
 * @description: 防抖函数:函数被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时
 * @param {Function} fn 要执行的函数
 * @param {Number} wait  wait毫秒后执行回调
 * @param {*} ...arr 传递给fn的参数
 */
function debounce(fn, wait, ...arr) {
  let timer = null;
  return () => {
    if (timer) {
      // 如果有一个函数在等待执行 清除定时器 下面重新计时
      clearTimeout(timer);
      timer = null; // 清空timer 下次重启定时器
    }
    // 设定时器/重置定时器
    timer = setTimeout(() => {
      fn(...arr); // wait时间后 执行回调 期间再触发debounce 需要重新等待
    }, wait);
  };
}
// 要防抖的函数
let actionFn = function(a, b) {
  console.log('回调', a, b);
};
setInterval(debounce(actionFn, 500, 'actionFn参数1', '参数2'), 1000); // 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(actionFn, 2000), 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
26

可以这样理解

函数触发停止一段时间后(期间不能再触发 debounce,否则将重新计时),再执行回调函数

# 机制:

防抖函数主要利用定时器的延迟执行特性,根据是否有定时器在等待执行:

  • 触发了一个事件后:如果有一个定时任务待执行,就清除定时器,重新计时。
  • 如果没有任务待执行,就定时执行这个事件。

# 应用场景:

  1. 表单的连续点击,防止重复提交。比如重复发送一篇文章。
  2. 类百度的搜索,连续输入等输入停止后再搜索。
  3. 一直拖动浏览器窗口,只想触发一次事件等。

# 节流函数(throttle):

# 概念:

规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行(单位时间内有事件被多次触发则,只生效一次)

# 生活中的栗子:

漏水的自来水水龙头,尽管水龙头里面有很多水(一直在触发事件),但还是一滴一滴的往下滴(单位事件内只生效一次)。

# 代码栗子:

/**
 * @description: 节流函数:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行
 * @param {Function} fn 要执行的函数
 * @param {Number} gapTime  单位时间
 * @param {*} ...arr 传递给fn的参数
 */
function throttle(fn, gapTime, ...arr) {
  let last = 0; // 上次执行时间 第一次马上执行
  return () => {
    let nowTime = Date.now(); // 当前时间
    // 当前时间-上次执行的时间是否超过间隔时间 就执行回调
    if (nowTime - last > gapTime) {
      fn(...arr); // ...arr为fn的参数
      last = nowTime; // 重置上次执行时间为当前时间 方便下次执行
    }
  };
}
let actionFn = (a, b) => {
  console.log('回调', a, b); // 要执行的函数
};
setInterval(throttle(actionFn, 1000, 'actionFn参数1', '参数2'), 10);
// 每隔10毫秒都会触发一次throttle,每隔一秒触发一次actionFn回调(1秒内再次触发被丢弃)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 机制:

节流函数根据时间差是否超过给定时间(gapTime)来决定是否触发回调。

# 应用场景:

  1. 自动保存草稿功能,当用户在输入的时候(一直触发事件),单位时间内只保存一次草稿。
  2. 游戏中的刷新率

# 作用和本质:

  • 防抖函数和节流函数主要解决的问题是:防止函数”短时间“的重复执行

  • 它们本质上是:在时间轴上控制函数的执行次数

# 应用实例,需要加个括号:

因为返回debouncethrottle返回的是一个函数,所以如果不是自动执行的事件监听回调,我们应该再后面加个(),执行返回的闭包函数。

document.onclick = () => {
  // throttle(actionFn, 1000) 这样不会执行 只返回了一个闭包函数
  throttle(actionFn, 1000, '执行函数参数1', '执行函数参数2')(); // 执行闭包函数
};
1
2
3
4

# 点个Star支持我一下~

最后更新时间: 8/2/2019, 12:38:18 PM