函数防抖主要就是防止频繁触发事件就会频繁触发回调,回调要是操作dom或者其他耗时工作,浏览器受不了。
函数防抖:
好比电梯需要上人,来一个人,就要等几秒再走,再来个人又要多等一样的时间,再来一样。
在网上看到也有个比较恰当的比喻,好比网络游戏法师施法,点击之后正在读进度条,你又点了一次,那只能从头再读,每次点都得从头读。
实现代码如下:
function debounce (func, wait) {
var lastCallTime
var lastThis
var lastArgs
var timerId
function startTimer (timerExpired, wait) {
return setTimeout(timerExpired, wait)
}
function remainingWait(time) {
const timeSinceLastCall = time - lastCallTime
const timeWaiting = wait - timeSinceLastCall
return timeWaiting
}
function shoudInvoking (time) {
return lastCallTime !== undefined && (time - lastCallTime >= wait)
}
function timerExpired () {
const time = Date.now()
// 一个劲猛点的话这个if里永远满足不了条件,只有你停下来等一会,就会有结果了
if (shoudInvoking(time)) {
return invokeFunc()
}
timerId = startTimer(timerExpired, remainingWait(time))
}
function invokeFunc () {
timerId = undefined
const args = lastArgs
const thisArg = lastThis
let result = func.apply(thisArg, args)
lastArgs = lastThis = undefined
return result
}
function debounced (...args) {
let time = Date.now()
lastThis = this
lastArgs = args
lastCallTime = time
// invokeFunc函数没结果之前,再点击多少次下边这个函数都不执行了.点击只会更改lastCallTime
// 更改了lastCallTime,
if (timerId === undefined) {
timerId = startTimer(timerExpired, wait)
}
}
return debounced
}
window.addEventListener('click', debounce(function (event) {
var p = document.createElement('p')
p.innerHTML = 'trigger'
document.body.appendChild(p)
return 'aaaa'
}, 500))
可以使用lodash 中的 debounce函数。省去自己写的麻烦。但是原理了解一下,没坏处。