防抖的原理:在n秒后执行触发的事件,如果在n秒内又触发了这个事件,就以新触发事件的事件为准,n秒后再执行该事件。
第一版:
function debounce(func, wait) {
var timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(func, wait);
}
}
this:
在debounce函数中,this指向window对象,我们需要将this指向func逻辑函数。
// 第二版
function debounce(func, wait) {
var timeout;
return function() {
var context = this;
clearTimeout(timeout);
timeout = setTimeout(function () {
func.apply(context);
}, wait);
}
}
event对象:
当使用debounce函数时,在func逻辑函数中打印event事件时,打印值为undefined,所以再修改一下代码:
// 第三版
function debounce(func, wait) {
var timeout;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context,args);
}, wait)
}
}
立刻执行:
有这样一个需求,希望立即执行函数,然后等到n秒后再重新出发执行。
那我们加一个 immediate 参数判断是否立即执行。
// 第四版
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (callNow) func.apply(context,args);
} else {
timeout = setTimeout(function () {
func.apply(context, args);
}, wait)
}
}
}
返回值:
逻辑函数func可能是有返回值的,所以我们要返回函数执行结果。但immediate为false时,执行的是setTimeout,将func.apply(context,args)赋值给变量,并将变量返回会一直是undefined,所以只在immediate为true时返回函数的执行结果。
// 第五版
function debounce(func, wait, immediate) {
var timeout, result;
return function() {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (callNow) result = func.apply(context, args);
}
else {
timeout = setTimeout(function() {
func.apply(context,args);
}, wait);
}
return result;
}
}
取消:
我希望通过一个按钮,点击后,取消防抖,再去触发,就可以立即执行。
// 第六版
function debounce(func, wait, immediate) {
var timeout, result;
var debounced = function() {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function() {
timeout = null;
}, wait);
if (callNow) result = func.apply(context,args);
}
else {
timeout = setTimeout(function () {
func.apply(context,args);
}, wait);
}
return result;
}
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
}
return debounced;
}
如何使用这个cancel函数?
// 例子:
var count = 1;
var container = document.getElementById('container');
function getUserAction(e) {
container.innerHTML = count++;
};
var setUseAction = debounce(getUserAction, 10000, true);
container.onmousemove = setUseAction;
document.getElementById("button").addEventListener('click', function(){
setUseAction.cancel();
})
网友评论