一、使用防抖的场景
改变页面大小的统计、滚动页面位置的统计、输入框连续输入的请求次数控制
二、工作流程
假设防止手抖进行多次付款操作的情景,点击addEventListener函数,让他延迟执行就需要加入setTimeout函数,但是仅仅延迟是不够的,因为如果在这个延时里用户继续点击的话,并不会重新计时, 因此需要加入clearTimeOut来清楚定时了,当用户点击以后,我们要清楚延时,然后重新设置定时,在规定时间内又有点击操作,那么接着清楚定时,并重新设置定时,如果在规定时间内没有点击那么就可以进行表单提交了;
举个例子,这个过程就好像我们进电梯一样,当我们按下电梯按钮,电梯门准备关闭,假设电梯门5s中自动关闭,但是在这五秒内有人又按下了电梯按钮,那么就需要清楚当前的定时,在新按下的那次操作重新倒计时,如果在5s内,没有人在按下电梯按钮了,那么就执行关门的操作;
三、 代码实现
const button = document.querySelector('input');
function payMoney () {
console.log('已买');
// 防抖第三个难点,在不使用防抖函数的时候this指向input按钮,但是用防抖this指向window
console.log(this)
}
function debounce (fun, delay) {
// 防抖第一个难点:采用高阶函数的形式,在防抖函数中返回一个函数,要不然就会出现,在监听函数定义的时候就执行了payMoney这个函数
let timer;
// 防抖的第二个难点:清楚定时所以要把需要清楚的内容放到timer这个变量中,所以把timer定义在clearTimeout和setTimeout前,但是清楚定时、执行定时这些操作时相互独立的,为了让这个操作之间有联系,所以就用到了作用域链的概念也就是必包;
return function() {
// 防抖的第三个难点: 解决this的指向问题
let context = this;
// 在js中函数中没有设置参数也是可以传入参数的,也就是每个执行函数是有可能被传入参数的
let args = arguements;
clearTimeout(timer);
timer = setTimeout(function(){
fun.apply(context, args);
},delay);
}
}
button.addEventListener('click', debounce(payMoney, 1000));