关于#javascript#的问题:防抖函数的作用域问题,有关改函数被多次触发,为什么可以获取到同一个timer

疑问求解:防抖函数的这个写法,重复触发后,timer 作为一个计时器被不停重置。但是我的理解是,在多次触发的时候 这个timer 与上一个 timer 是存在于同一个作用域内的吗?也就是此时的timer 与上一个timer 为什么会是同一个这个问题。可能是我钻牛角尖了,我错误的认为这个方法被触发的时候,是两个独立的作用域,但是我不理解为什么。


```javascript
var btn = document.getElementById('btn');
        function debounce (fn, delay) {
            let timer = null
            return function () {
                // 在规定时间内再次触发会先清除定时器后再重设定时器
                console.log(timer)
                clearTimeout(timer);
                timer = setTimeout(function () {
                    console.log(this)
                    fn.apply(this, arguments);
                }, delay);
            }
        }
        function fn () {
            console.log('防抖')
        }
        btn.onclick = function () {
            debounce(fn, 3000)()
        }


```

这个问题涉及到函数闭包的知识点。你可以看到,timer这个变量是在debounce函数中定义的,所以timer存在于debounce的作用域中,而我们调用的函数是debounce的返回值。正常情况下,debounce函数返回结果之后,它的生命周期就结束了,然后它的返回值当中包含着timer的引用,所以timer始终没有被垃圾回收掉,所以debounce函数的作用域也就一直存在,而无论调用多少次的onClick,它所用到的timer都是最开始debounce函数中的那个timer.

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/160520
  • 以下回答来自chatgpt:

    首先,防抖函数的作用是减少函数重复执行的次数,而不是让函数不被执行。防抖函数可以通过一个计时器来进行实现,例如在每次触发防抖函数时,先清除之前的计时器,然后重新设置一个新的计时器,当计时器时间到达时执行函数,这样可以保证函数只被执行一次。

    当防抖函数被多次触发时,实际上每次触发都会执行一次该函数,但在函数内部使用的计时器是同一个,因为该计时器是使用闭包的方式保存在函数内部的。所以每次触发并不会创建一个新的作用域,而是在同一个作用域内执行,并且可以访问到上一次执行时创建的计时器,以此来达到防抖的效果。

    下面是一个简单的防抖函数的实现及示例代码:

    function debounce(func, delay) {
      let timerId;
    
      return function() {
        clearTimeout(timerId);
    
        timerId = setTimeout(() => {
          func.apply(this, arguments);
        }, delay);
      }
    }
    
    function onInput() {
      console.log('input event fired');
    }
    
    document.querySelector('input').addEventListener('input', debounce(onInput, 500));
    

    上述代码中,防抖函数debounce接收一个函数作为参数func和一个时间间隔delay,返回一个新的函数用于实际执行。在新函数内部使用clearTimeout先清除之前的计时器,然后重新设置新的计时器,并在计时器时间到达时执行传入的函数。示例代码中,输入框的input事件被包装成一个防抖函数,当连续多次输入时,只有最后一次输入会触发函数。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^