什么是函数节流与函数防抖
举个栗子,我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放(以前是,现在不知道)中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源。再举个栗子,假设电梯一次只能载一人的话,10 个人要上楼的话电梯就得走 10 次,是一种浪费资源的行为;而实际生活正显然不是这样的,当电梯里有人准备上楼的时候如果外面又有人按电梯的话,电梯会再次打开直到满载位置,从电梯的角度来说,这时一种节约资源的行为(相对于一次只能载一个人)。
- 函数节流: 指定时间间隔内只会执行一次任务;
- 函数防抖: 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。
实现
函数节流
函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。以下是监听页面元素滚动的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function throttle(fn, wait) { var previous = 0 var timer = null return function () { var context = this var args = arguments if (!previous) { previous = Date.now() fn.apply(context, args) } else if (previous + wait >= Date.now()) { if (timer) { clearTimeout(timer) timer = null } timer = setTimeout(function () { previous = Date.now() fn.apply(context, args) }, wait) } else { previous = Date.now() fn.apply(context, args) } } }
|
throttle 应用场景
函数节流有哪些应用场景?哪些时候我们需要间隔一定时间触发回调来控制函数调用频率?
- DOM 元素的拖拽功能实现(mousemove)
- 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
- 计算鼠标移动的距离(mousemove)
- Canvas 模拟画板功能(mousemove)
- 搜索联想(keyup)
- 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次
函数防抖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function debounce(fn, wait) { var timer = null; return function () { var context = this var args = arguments if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(function () { fn.apply(context, args) }, wait) } }
|
debounce 应用场景
函数去抖有哪些应用场景?哪些时候对于连续的事件响应我们只需要执行一次回调?
- 每次 resize/scroll 触发统计事件
- 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
ref: http://justclear.gitlab.io/throttle-and-debounce/
ref: https://segmentfault.com/a/1190000008768202
ref: https://github.com/hanzichi/underscore-analysis/issues/20
ref: http://www.cnblogs.com/fsjohnhuang/p/4147810.html