防抖:
应用场景:
1)改变页面大小的统计
2)滚动页面位置的计算
3)输入框连续输入的请求次数的控制
4)防止表单多次提交
防抖函数的5个难点:
1)如何避免防抖函数的立即执行,即未点击按钮,就调用函数造成输出? --- 高阶函数, 防抖函数返回一个函数,然后被防抖函数《执行函数》放在返回的函数内部;
2)clearTimeout清除定时变量放在设置定时返回变量前面
3)让独立的执行函数产生联系,即不能每次点击的时候都创建timer,清除timer、设置定时,会导致起不到防抖的效果; ---- 使用作用域链/闭包,在return返回的函数《执行函数》外面定义timer变量,使得每次都访问同一个变量timer。
4)this的指向,由于setTimeout回调函数this执行window的原因,运行时候我们需要将this的指向改变为按钮;---- 先将 this保存,然后使用call方法显示改变this的指向;
5)执行函数传入参数的问题 ---- 使用arguments对象进行保存
const btn = document.getElementsByClassName('button')
// 执行函数
function payMoney(){
console.log('已剁手')
}
// 1、执行函数--高阶函数
function debounce(fn){
return function(){
fn()
}
}
// 2、设置定时
function debounce(fn,delay){
return function(){
setTimeout(function(){
fn()
},delay)
}
}
// 清除定时
function debounce(fn, delay){
return function(){
clearTimeout(timer)
timer = setTimeout(function(){
fn()
}, delay)
}
}
// 使用闭包/作用域链来实现清除
function debounce(fn, delay){
let timer
return function(){
clearTimeout(timer)
timer = setTimeout(function(){
fn()
},delay)
}
}
// 解决this指向和参数问题
function debounce(fn, delay){
let timer
return function(){
let context = this
let args = arguments
clearTimeout(timer)
timer = setTimeout(function(){
fn.call(context, args)
},delay)
}
}
btn.addEventListener('click', debounce(payMoney, 1000))