前言
关于移动端的scroll的优化,还有轮播图的实现是面试中经常考察的问题,顺带就会涉及到节流和去抖的原理,说不定柯里化呀,来实现个bind呀,什么的。。用ES6实现呀~balabala就出现了。。今天终于搞懂了这两货是怎么回事,遂来总结一下啦!第一次听到他俩是去年吧 囧。。
去抖(debounce)
debounce的效果是:为了避免函数频繁执行,我们设定一个delay,如果本次执行距离上一次的时间少于delay那么我们不会执行他。
他和节流很大一个区别就是如果你不停的去触发一个去抖过的函数,那么它永远也不会执行。
那么它适合那些场景呢?
每次 resize/scroll 触发统计事件
文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
简而言之,停下来才会触发的事情啦~。
懒加载如果用去抖,只有停下来才会触发我们的监听事件(所以应该用节流)
去抖的实现:
function debounce(func, delay) {
return function(args) {
var _this = this
var _args = args
clearTimeout(func.id)
func.id = setTimeout(function() {
func.call(_this, _args)
}, delay)
}
}
去抖的实现很容易,每次触发函数时,clearTimeout就好,如果你太快,那之前的timeout就没咯~
节流(throttle)
节流也需要运用到setTimeout,他和去抖的区别是,如果你频繁的触发事件,事件会按照你指定的delay来触发。就想BIUBIUBIUBIUBIU。。。。会节流成 BIU BIU BIU。。。。。不停的触发,函数会按照你指定的频率来执行。不会像debounce那样,就不执行了。
他适合的场景就比较多了,高频转低频的场景都很棒:
DOM 元素的拖拽功能实现(mousemove)
射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
计算鼠标移动的距离(mousemove)
Canvas 模拟画板功能(mousemove)
搜索联想(keyup)
监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次
实现如下:
function throttle(func, delay) {
var last, deferTimer
return function() {
var _this = this
var _args = arguments
var now = +new Date()
if(last && now < last + delay) {
//如果 now - last < 我们的delay。我们取消掉他
clearTimeout(deferTimer)
deferTimer = setTimeout(function() {
last = now
func.apply(_this, _args)
}, delay)
}else {
//如果now - last > delay,我们立即执行他
last = now
func.apply(_this, _args)
}
}
//这个if else的结果就是,反复执行的时候会不停的进行时间判断
//如果now - last > delay也就是间隔大于了delay我们会触发他。
//这就避免了debounce永远不执行的命运。。当然只有间隔大于delay
//的时候。 当间隔小于delay , now - last < delay,我们用类似于debounce的方式过滤掉间隔小于delay的触发。
}
结语
= =。话不多说。希望能有面试哇!!Orz