为什么防抖和节流?
我们使用窗口的 resize,scorll,mousemove,mousehover;输入框等校验时,如果事件处理函数调用无限制,会加剧浏览器的负担,尤其是执行了操作 DOM 的函数,那不仅造成计算资源的浪费,还会降低程序运行速度,甚至造成浏览的奔溃,影响用户体验。
防抖和节流有什么区别?
防抖:就是触发多次事件,最后一次执行事件处理函数。在事件被触发后,等待一段时间(例如100毫秒),如果在这段时间内没有再次触发事件,才执行相应的操作。如果在等待时间内又触发了事件,则重新计时等待时间。
节流:隔一段时间执行一次事件处理函数。在一定时间间隔内(例如每200毫秒),只允许事件执行一次。如果在这段时间内再次触发事件,忽略该事件,直到时间间隔过去,才允许下一次事件执行
防抖和节流有什么具体应用场景?
防抖:适用于那些在短时间内频繁触发事件的情况,比如输入框输入事件、窗口调整事件。防抖可以避免在用户还在输入过程中就立即执行操作,而是等待用户停止输入一段时间后再执行操作,减少频繁的操作执行。
节流:适用于那些需要限制事件触发频率的情况,比如滚动事件、鼠标移动事件、浏览器滚动监听事件。通过节流,可以确保在一定时间内只执行一次事件处理函数,避免过多的计算和操作。
防抖例子:
// 防抖函数
let deBounce = (fn, delay) => {
let timer = null
return function(...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn(...args)
}, delay)
}
}
let oInput = document.getElementsByTagName('input')[0]
// 模拟请求
let ajax = message => {
let json = { message }
console.log(JSON.stringify(json))
}
let doAjax = deBounce(ajax, 200)
// 键盘弹起执行
oInput.addEventListener('keyup', e => {
doAjax(e.target.value)
})节流例子:
/*
* 连续点击只会1000执行一次btnClick函数
*/
let obutton = document.getElementsByTagName('button')[0]
// 如果用箭头函数,箭头函数没有arguments,也不能通过apply改变this指向
function btnClick() {
console.log('我响应了')
}
/*
方法1: 定时器方式实现
缺点:第一次触发事件不会立即执行fn,需要等delay间隔过后才会执行
*/
let throttle = (fn, delay) => {
let flag = false
return function(...args) {
if (flag) return
flag = true
setTimeout(() => {
fn(...args)
flag = false
}, delay)
}
}
/*
方法2:时间戳方式实现
缺点:最后一次触发回调与前一次的触发回调的时间差小于delay,则最后一次触发事件不会执行回调
*/
let throttle = (fn, delay) => {
let _start = Date.now()
return function(...args) {
let _now = Date.now(),
that = this
if (_now - _start > delay) {
fn.apply(that, args)
start = Date.now()
}
}
}
// 方法3:时间戳与定时器结合
let throttle = (fn, delay) => {
let _start = Date.now()
return function(...args) {
let _now = Date.now(),
that = this,
remainTime = delay - (_now - _start)
if (remainTime <= 0) {
fn.apply(that, args)
} else {
setTimeout(() => {
fn.apply(that, args)
}, remainTime)
}
}
}
/*
方法4:requestAnimationFrame实现
优点:由系统决定回调函数的执行机制,60Hz的刷新频率,每次刷新都会执行一次回调函数,不
会引起丢帧和卡顿
缺点:1.有兼容性问题2.时间间隔有系统决定
*/
let throttle = (fn, delay) => {
let flag return function(...args) {
if (!flag) {
requestAnimationFrame(function() {
fn.apply(that, args)
flag = false
})
}
flag = true
}
}
obutton.onclick = throttle(btnClick, 1000)



