防抖和节流函数实现
NOxONE 7/20/2022 js
# 1. 防抖
防抖
(debounce
):在第一次触发事件时,不立即执行函数,而是给出一个延迟
。若在延迟时间内,不再触发事件那么执行函数;若在延迟时间内再次触发事件,那么以最后一次触发的时机重新计算延迟时间再执行函数。说白了,就是解决用户手抖
的情况(#...#)
function debounce(fn, delay = 500) {
let timer = null
return function (...args) {
timer && clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
// test
let log = debounce((a) => console.log(a))
btn.onClick = log(1)
wait!!! 这里防抖虽然是防抖了,但是给用户的感觉是有 500ms 的延迟,所以我想做个优化,让它第一次就开始执行了,且上次执行完毕后又可以立即执行,即用户手抖开始前立刻执行函数,用户手抖结束后再执行函数,然后继续重复下一轮,总之不能为了面试而面试对吧?
function myDebounce(fn, delay = 500, immediate = 1) {
// immediate 为立即执行标志,1默认开始立即执行
let timer = null
return function (...args) {
timer && clearTimerout(timer)
if (immediate) {
immediate ^= 1 // 众所周知:1^1==0; 0^1==1
fn.apply(this, args)
timer = setTimeout(() => (immediate ^= 1), delay)
} else
timer = setTimeout(() => {
fn.apply(this, args)
immediate ^= 1
}, delay)
}
}
# 2. 节流
节流
(throttle
):如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效
function throttle(fn, hold = 500) {
let timer = null
let start = +new Date()
return function (...args) {
timer && clearTimeout(timer)
let end = +new Date()
if (end - start >= hold) {
start = end
fn.apply(this, args)
} else timer = setTimeout(() => fn.apply(this, args), hold)
}
}
# 3. 防抖和节流的区别
防抖:函数在等待一个 delay 延迟后再执行
节流:函数在一个 hold 时间段内只执行一次
简单来说:如果在用户一直点击的情况下:防抖一直都不会触发,直到用户停下来后等待 delay 延迟才会触发,节流是每隔 hold 触发一次