力扣刷题:函数防抖

118 阅读2分钟

前言:锻炼自己的思想,规范自己的编程思路。

问题:

请你编写一个函数,接收参数为另一个函数和一个以毫秒为单位的时间 t ,并返回该函数的 函数防抖 后的结果。

函数防抖 方法是一个函数,它的执行被延迟了 t 毫秒,如果在这个时间窗口内再次调用它,它的执行将被取消。你编写的防抖函数也应该接收传递的参数。

例如,假设 t = 50ms ,函数分别在 30ms 、 60ms 和 100ms 时调用。前两个函数调用将被取消,第三个函数调用将在 150ms 执行。如果改为 t = 35ms ,则第一个调用将被取消,第二个调用将在 95ms 执行,第三个调用将在 135ms 执行。

image-20230615192944819.png

示例:

输入:
t = 50
calls = [
  {"t": 50, inputs: [1]},
  {"t": 75, inputs: [2]}
]
输出:[{"t": 125, inputs: [2]}]
解释:
let start = Date.now();
function log(...inputs) { 
  console.log([Date.now() - start, inputs ])
}
const dlog = debounce(log, 50);
setTimeout(() => dlog(1), 50);
setTimeout(() => dlog(2), 75);

第一次调用被第二次调用取消,因为第二次调用发生在 100ms 之前
第二次调用延迟 50ms,在 125ms 执行。输入为 (2)。

思路:

先声明了一个名为timeout 的变量,用于存储定时器的 ID。

接下来,返回一个新的函数。这个函数使用了剩余参数(...args),它允许我们将不定数量的参数表示为一个数组。

在这个新函数中,首先调用clearTimeout(timeout) 来清除之前设置的ID定时器(如果有)。然后调用 setTimeout 函数来设置一个新的定时器ID,该定时器在延迟 t 毫秒后执行一个箭头函数。这个箭头函数调用了 fn.apply(this, args) 来执行传入的函数fn,并将当前上下文(this)和参数(args)传递给它。

这样,在每次调用返回的新函数时,都会清除之前设置的定时器并设置一个新的定时器。如果在延迟时间内再次调用该函数,则之前设置的定时器将被清除,从而取消了之前调用的执行。

基于上述思考,代码如下:

var debounce = function(fn, t) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn.apply(this, args), t);
  }
};

执行结果如下图:

image-20230615192930452.png