You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// leading 默认不开启立即调用functiondebounce(func,wait,leading=false){lettimerIdfunctiondebounced(...args){constlastThis=thisconstlastArgs=argstimerId&&clearTimeout(timerId)if(leading){constinvokeNow=!timerIdtimerId=setTimeout(function(){timerId=null},wait)invokeNow&&func.apply(lastThis,lastArgs)}else{timerId=setTimeout(function(){func.apply(lastThis,lastArgs)},wait)}}returndebounced}wrapperDom.onmousemove=debounce(doEvent,1000,true)
阅读 lodash 源码学防抖
前言
在介绍防抖之前,我们先看下面这个例子:鼠标滑过黑布触发
onmousemove
事件。运行效果图如下:
从效果图可以看出,浏览器处理数字累加还是蛮流畅的,因为这个例子的事件函数相对简单。假设 1s 触发 1000 次事件,且事件是发送 ajax 请求,那么浏览器处理时就会出现卡顿。
为了解决这类问题,通常使用防抖(debounce)和节流(throttle)的方案。
介绍
防抖指的是触发事件后,在
n
秒内函数只能执行一次,如果触发事件后在n
秒内又触发了事件,则会重新计算函数,延长执行时间。实现
根据上面的介绍,我们现在可以简单实现下:
运行效果图如下:
现在不管你在 1s 内鼠标移动多少次,它都只在移动完 1s 后再触发事件。
细心的你应该已经发现了,上面的实现过程中,this 的指向和 MouseEvent 对象参数发生了改变。那么现在我们来修复这两个已知问题,如下:
立即调用
虽然上面的防抖函数已经基本完成了,但是产品经理有这么个需求:添加一个控制立即调用函数
func
的开关。运行效果图如下:
返回值
如果调用的
func
函数有返回值怎么办?我们得添加它的返回值。代码实现如下:注意:当 leading 为 false 的时候,因为使用了 setTimeout ,我们将
func.apply(context, args)
的返回值赋给变量,最后再 return 的时候,值将会一直是 undefined,所以我们只在 leading 为 true 的时候返回函数的执行结果。虽然实际开发中,这个返回值几乎用不上,但是作为工具库的 Lodash 考虑情况比较全面。
取消
如果我不想等待防抖函数执行了,是否可以取消呢?答案是可以的哈~,下面我们为防抖函数添加一个取消属性即可。
题外话
或许有小伙伴会问,如果我想要调试 Lodash 源码怎么办?有没有方案推荐呢?
有的哈。我已经把它总结到这篇文章了。戳这里学习
结语
本文到这里就结束了,通过文章我们了解到什么是防抖以及它的实现原理,使用防抖函数可以解决项目中,搜索框输入关键字后间隔一段时间,才会请求获取建议列表......
在前端面试中,防抖函数还是一道高频考题,希望小伙伴们看完本文后能够顺利拿下。
参考文献
Lodash 源码
冴羽的博客
The text was updated successfully, but these errors were encountered: