防抖和节流
防抖(debounce)
基于上述场景,首先提出第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:
- 如果在200ms内没有再次触发滚动事件,那么就执行函数
- 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时
效果:如果短时间内大量触发同一事件,只会执行一次函数。
实现:既然前面都提到了计时,那实现的关键就在于setTimeout这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现:
节流(throttle)
节流,顾名思义,控制流量。用于用户在与页面交互时控制事件发生的频率,一般场景是单位的时间或其它间隔内定时执行操作。一段时间内,事件在每次到达我们规定的间隔 n 秒时触发一次。
特点:每等待某种间隔后,进行操作持续触发并不会执行多次到一定时间 / 其它间隔 ( 如滑动的高度 )再去执行应用场景 ( 注:因以下例子涉及公司业务内容,不进行实际页面截图展示 ):埋点场景。商品搜索列表、商品橱窗等,用户滑动时 定时 / 定滑动的高度 发送埋点请求
解决方法:我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(类似于技能冷却时间)。
防抖:用户操作很频繁,但是只是执行一次
节流:用户操作很频繁,但是把频繁的操作变为少量操作【可以给浏览器有充裕的时间解析代码】
函数防抖的代码实现
函数防抖的实现(函数在执行一次之后,若在规定的时间内再次执则重新开始计时,在时间内无法执行该函数)
思路:在规定时间内未触发第二次,则执行
function debounce (fn,delay){
//利用闭包保存定时器
let timer = null
return function (){
let context = this
let arg = arguments
//在规定时间内再次触发会先清除定时器后重新设定时器
clearTimeout(timer)
timer = setTimeout(function (){
fn.apply(context,arg)
},delay)
}
}
function fn(){
console.log('防抖')
}
addEventListener('scroll',debounce(fn,1000))
函数节流的代码实现
函数节流的实现(函数在执行一次之后,在规定的时间内无法再次执行,直至时间到达)
思路:在规定时间内只触发一次
function throttle(fn,delay){
//利用闭包保存时间
let prev = Date.now()
return function(){
let context = this
let arg = arguments
let now = Date.now()
if(now - prev >= delay){
fn.apply(context,arg)
prev = Date.now()
}
}
}
function fn(){
console.log('节流')
}
addEventListener('scroll',throttle(fn,1000))
函数防抖与节流---面试题
正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿)
防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发,只会执行最后一次
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发

浙公网安备 33010602011771号