为什么节流函数中的定时器ID没有按预期变化?

新手上路,请多包涵

关于节流函数中定时器id的变化问题

        let i = 0
        function mouseMove() {
            document.querySelector('.box').innerHTML = i++
        }
        function save(fn, t) {
            let timer = null

            return function () {

                if (!timer) {
                    timer = setTimeout(function () {

                        fn()
                        console.log(timer)
                        timer = null
                    }, t)
                }

            }
        }

        document.querySelector('.box').addEventListener('mousemove', save(mouseMove, 2000))

试图在setTimeout期间打印了这个定时器

最后在盒子内没有间歇的滑动鼠标,打印出来的timer没有3是为啥? 后面无论我怎么滑动鼠标,打印的数字都是按顺序递增的,很奇怪。而且把打印放在fn前后结果都一样。

阅读 464
avatarAI BotBETA
### 解释

在你的节流函数实现中,`timer` 变量被设计为在 `setTimeout` 回调执行后重置为 `null`。这意味着每次 `setTimeout` 触发的函数执行完毕后,`timer` 都会变成 `null`,从而允许在下一次事件触发时重新设置一个新的 `setTimeout`。

关于你提到的 "打印出来的 `timer` 没有3" 的问题,这是因为 `timer` 的值在你打印它的时候已经被重置为 `null` 了。在 `setTimeout` 的回调函数中,`fn()` 被调用之后,紧接着 `timer = null` 被执行,这就覆盖了之前 `setTimeout` 返回的定时器ID。

每次你移动鼠标时,如果 `timer` 为 `null`,则会创建一个新的 `setTimeout`,并且这个新的 `setTimeout` 会返回一个新的定时器ID。但是,由于这个新的定时器ID只存在于 `setTimeout` 的回调被调用之前的那一小段时间内(即在 `fn()` 调用和 `timer = null` 执行之间),因此你很少有机会捕获到这个新ID(因为它几乎立即就被重置为 `null` 了)。

如果你在 `fn()` 调用之前打印 `timer`,你会看到每次事件触发时生成的定时器ID(在它们被重置为 `null` 之前)。然而,由于 `console.log(timer)` 在 `fn()` 调用之后执行,你总是看到 `null`,因为此时 `timer` 已经被重置了。

如果你想要捕获并观察这些定时器ID,你需要在它们被重置之前打印它们,比如在调用 `fn()` 之前。但是请注意,这样做会改变节流函数的正常行为,因为它会延迟 `timer` 被重置为 `null` 的时间。
1 个回答

setTimeout 的返回值 timeoutID 是一个正整数,表示由 setTimeout() 调用创建的定时器的标识符。可以将这个值传递给 clearTimeout() 来取消该定时器。

这个正整数仅表示定时器 ID,不具有其他含义,不一定是 1,2,3……。当然,大部分浏览器使用自增 id 实现。如果在其他地方调用了 setTimeout 可能会导致某个 ID 被其他定时器占有。

推荐问题
宣传栏