防抖节流
1.防抖
控制高频函数执行的次数,n秒内执行一次,当n秒内再次触法,则重新计算
应用:
窗口resize
scroll(窗口停止滚动触发操作)
表单验证
提交
输入框查询
let count = 0 const doSome = debounce(doSomething,3000) container.onmousemove = doSome function doSomething(e){ container.innerText = ++count } btn.onclick = function () { doSome.cancel() }
function debounce(fun,wait,immediate){
let timeout,result
const debounced = function () {
const context = this
const args = arguments
if(timeout)clearTimeout(timeout)
if(immediate){
let callNow = !timeout
timeout = setTimeout(()=>{
timeout = null
},wait)
if(callNow)result = fun.apply(context,args)
}else{
timeout = setTimeout(()=>{
result = fun.apply(context,args)
},wait)
}
return result
}
debounced.cancel = function () {
clearTimeout(timeout)
timeout = null
}
return debounced
}
2.节流
高频函数持续执行,每隔一段时间执行一次
应用场景:
拖拽每隔一段时间进行操作
射击游戏每隔一段时间上子弹
scroll(每个一段时间执行操作)
计算鼠标移动距离
let count = 0 container.onmousemove = throttle(doSomething,1000,{leading:true,trailing:true}) function doSomething(e){ container.innerText = ++count }
// 时间戳实现
function throttle1(func,wait){
let old = 0
let context,args
return () => {
context = this
args = arguments
const now = new Date().valueOf()
if(now - old > wait){
func.apply(context,args)
old = now
}
}
}
// 定时器实现
function throttle2(func,wait){
let timeout,context,args
return () => {
if(!timeout){
context = this
args = arguments
timeout = setTimeout(() => {
func.apply(context,args)
timeout = null
},wait)
}
}
}
// 完完整版
function throttle(func,wait,option){
let old = 0
let context,args
let timeout
if(!option)option = {}
const { leading,trailing } = option
return () => {
context = this
args = arguments
const now = new Date().valueOf()
if(leading === false && !old){
old = now
}
if(now - old > wait){
// 执行第一次
func.apply(context,args)
old = now
if(timeout){
clearTimeout(timeout)
timeout = null
}
} else if(!timeout && trailing){
// 执行最后一次
timeout = setTimeout(() => {
func.apply(context,args)
old = now
timeout = null
},wait)
}
}
}