首页 > 解决方案 > JavaScript 中的简单去抖动函数

问题描述

给定一个去抖函数如下:

const debounce = (fn, delay) => {
  let timer;
  return () => {
    if(timer) clearTimeout(timer);
    timer = setTimeout(fn, delay)
  }
}

document.getElementById("mybutton").addEventListener('click', debounce(()=>console.log("Clicked"),1000))

每次触发按钮时,它都会调用“去抖动”功能,我的问题是“计时器”变量怎么可能没有被重新初始化?据我所知,“let”关键字作用域是块作用域,那么“计时器”如何保存上次调用的 setTimeOut 标识?

每条评论都值得赞赏,谢谢。

标签: javascript

解决方案


每次触发按钮时,它都会调用“去抖动”功能......

不,它只被调用一次——当你添加事件处理程序时。代码.addEventListener('click', debounce(()=>console.log("Clicked"),1000)) 调用 debounce并将其返回值传递给addEventListener,与foo(bar()) 调用 bar并将其返回值传递给foo. 的返回值debounce是一个函数;该函数是传递给的函数addEventListener,因此函数是每次事件发生时调用的函数,而不是debounce.

这就是为什么只有一个timer变量,因为只有一次调用debounce. 它返回的函数关闭变量。


在评论中,您要求进行一些澄清:

另一个相关的问题是,当“去抖动”返回内部函数时,该内部函数被传递给“addEventListener”,在另一个“点击”事件之后返回的函数是否保持不变?

是的。这是一个功能。这段代码:

document.getElementById("mybutton").addEventListener('click', debounce(()=>console.log("Clicked"),1000));

与此代码完全相同,除了此代码具有上面代码没有的标识符之外:

const eventHandlerFunction = debounce(()=>console.log("Clicked"),1000);
document.getElementById("mybutton").addEventListener('click', eventHandlerFunction);

该问题的另一种说法是:是否每次单击按钮时都不会重新创建返回函数的执行上下文

调用的执行上下文debounce仅在您调用时创建一次debounce。该执行上下文包含timer变量。只要有东西引用它们,上下文(以及变量)就会被保留。函数debouncecreates(eventHandlerFunction在上面的代码中)对它们有引用,所以只要该函数存在,它们就存在。

(因为在第一次单击按钮后“谴责”函数执行已经消失,我应该说在第一次单击按钮后“计时器”变量不再存在。)?

timer只要变量继续存在,变量就会继续存在eventHandlerFunction。该函数将继续存在,直到对它的所有引用都被释放——在这种情况下,要么将其从元素的click事件处理程序列表中删除,要么当元素本身消失时。


推荐阅读