Debounce
- 每次触发函数,都将原来的定时器清空
- 一直触发函数,那定时器就一直在被清空,
- 直到下一次触发函数间隔超过了延迟时间, 回调函数才会被执行
这是防抖的原理
function debounce(fun, delay, immediate){
var timeout = null,
result = null
return function(){
var _this = this
var args = arguments
// 在 setTimeOut 中, this 指向 window,
// func 原有的 this 以及 arguments 会丢失
// 所以在这里保存下来,使用 apply(call),将这个保存下来的参数传递进去
timeout ? clearTimeout(timeout) : ''
// 希望事件触发之后,先立即执行一次,
// 下一次执行才延迟
if(immediate){
// 如果在一次事件触发过程中,定时器的回调函数被执行过
// timeout 就是有值的,而不是 null
// 所以 !null == true 的时候,就是回调函数函数可以运行的时候(canRun)
var canRun = !timeout
timeout = setTimeout(function(){
timeout = null
}, delay)
canRun ? result = fun.apply(_this, args) : ''
}else{
timeout = setTimeout(function(){
fun.call(_this, args)
}, delay)
}
return result
}
}
这几行代码重点解释一下:
timeout = setTimeout(function(){
timeout = null
}, delay)
希望每次都是在间隔结束后立即触发函数,而不是等延迟结束再触发。这么说可能有点绕,设想: 延迟时间为10s
,第一次触发需要debounce
的事件,然后停止事件的触发操作;等待10s
,回调函数执行。
第二次触发,在等待10s
,回调函数执行。这就是else代码块
里面的逻辑。
然后上面的代码是: 如果timeout
为null
,就让其立即执行,但是执行之后,要将timeout
置为null
,否则下次就会得到canRun
的值为false
,不会触发回调函数。
Throttle
节流就是对于频繁触发的事件,在一段时间内只触发一次。
function throttle(fun, delay){
var prev = 0
return function(){
var now = +new Date()
var _this = this
var args = arguments
if(now - prev > delay){
fun.apply(_this, args)
prev = now
}
}
}
function throttle(fun, delay){
var timeout = null
return function(){
var _this = this
var args = arguments
if(!timeout){
timeout = setTimeout(function(){
timeout = null
fun.apply(_this, args)
}, delay)
}
}
}
区别
防抖:当你患有癫痫的手一顿操作使其事件一直触发,某个时候停了,并且停顿的时间超过延迟时间之后,执行一次函数。
节流:当你患有癫痫的手一直触发某个操作,但是能让函数在一段时间内只触发一次。
网友评论