手写Debounce|手写Debounce 防抖函数遇到的坑
最开始写的防抖函数
function debounce(fn, delay) {
let timer;
// 返回一个函数,这个函数会在一个时间区间结束后的 delay 毫秒时执行 fn 函数
return function () {
// 保存函数调用时的上下文和参数,传递给 fn
let context = this
let args = arguments
// 每次这个返回的函数被调用,就清除定时器,以保证不执行 fn
clearTimeout(timer)
// 当返回的函数被最后一次调用后(也就是用户停止了某个连续的操作),
// 再过 delay 毫秒就执行 fn
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
写两个按钮来执行
这里 问题就来了 比如点击两次 这样做的话就会出现 2秒之后 打印2次console
function btnclick() {
debounce(function () {
console.log('触发按钮的点击事件')
}, 1000)()
}
但是下面这样写就是正确的 连续点击两次 最后一次点击两秒之后打印console
let btn = document.getElementById('btn')
btn.addEventListener('click', debounce(() => {
console.log('监听按钮')
}, 1000))
这里困惑了很久才发现 实际上事件监听相当于是吧debounce函数的返回值先拿到 再在点击的时候执行这个返回函数
而触发按钮是每次点击都会执行debounce这个函数 执行debouce就会初始化 let timer 下面的clearTimeout就没有办法清除定时器
解决办法: 直接把这个timer给this 每次执行的时候都不会初始化timer
当然 比较笨的办法就是先把debouce函数的返回函数缓存下来 点击的时候才执行
let d = debounce(function () {
console.log('事件函数')
}, 1000)
【手写Debounce|手写Debounce 防抖函数遇到的坑】function btnclick() {
d()
}
function debounce(fn, delay) {
// 返回一个函数,这个函数会在一个时间区间结束后的 delay 毫秒时执行 fn 函数
return function () {
// 保存函数调用时的上下文和参数,传递给 fn
let context = this
let args = arguments
// 每次这个返回的函数被调用,就清除定时器,以保证不执行 fn
clearTimeout(this.timer)
// 当返回的函数被最后一次调用后(也就是用户停止了某个连续的操作),
// 再过 delay 毫秒就执行 fn
this.timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
推荐阅读
- 手写|手写 React-Native 方法调用式的 Modal 弹框、Toast 提示
- spring5源码系列--循环依赖|spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖
- 手写我心day12
- Throttle|Throttle 和 Debounce 的本质及一个简单的实现
- vue的mvvm原理解析及手写一个
- 手写我心day15
- JMeter手写脚本,及注意事项。
- 自己写一个pow()函数
- 刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!
- 根据tapable调试结果,手写SyncHook实现