一、防抖函数介绍
防抖:在一系列连续的事件触发后,只有最后一个事件才会触发处理函数
应用场景:用户在输入框中连续输入一串字符时,可以通过防抖策略,在输入完后,才执行查询的请求,可以有效减少请求次数,节约请求资源
二、功能实现
2.1基本功能
主要利用定时器实现,当多次触发事件,会检查上次timer是否存在(利用了闭包),存在则清除,然后重新设定定时器
function debounce(fn, delay) {
let timer = null;
const _debounce = function () {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn();
timer = null;
}, delay);
};
return _debounce;
}
运用
input.oninput =debounce(function(){
console.log('111');
},2000);
2.2优化参数和this指向问题
有时候fn函数需要使用event,或者使用this.value获取输入框的值,所以需要将参数传递给fn函数,并将fn的this进行绑定。
function debounce(fn, delay) {
let timer = null;
const _debounce = function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
//这里fn是独立函数调用,this指向了window,所以需要绑定this,指向为当前绑定事件的对象
fn.apply(this, args);
timer = null;
}, delay);
};
return _debounce;
}
运用
input.oninput =debounce(function(event){
console.log('111',event,this.value);
},2000);
2.3取消执行
函数也是对象,所以可以直接给返回的函数添加一个取消函数。
//取消功能
_debounce.cancel = function () {
if (timer) clearTimeout(timer);
timer = null;
};
运用
const debounceFn=debounce(function(event){
console.log('111',event,this.value);
},2000);
input.oninput =debounceFn
btn.onclick = function () {
debounceFn.cancel();
};
2.4立即执行
需要使用一个参数immediate决定是否立即执行,在使用isInvoke标记是否已经执行过了
function mydebounce(fn, delay, immediate = false) {
let timer = null;
let isInvoke = false; //是否执行过了
let res = undefined;
const _debounce = function (...args) {
if (timer) clearTimeout(timer);
//第一次执行
if (!isInvoke && immediate) {
fn.apply(this, args);
isInvoke = true;
return;
}
timer = setTimeout(() => {
res = fn.apply(this, args);
timer = null;
}, delay);
};
//取消功能
_debounce.cancel = function () {
if (timer) clearTimeout(timer);
timer = null;
isInvoke = false;
};
return _debounce;
}