函数防抖
前言
- 为什么需要使用防抖函数
当一个事件触发太多的时候会出现性能问题,比如
mousemove
、resize
、scroll
等,看一个没有任何防抖的mousemove
事件
- 什么是防抖? 简单就是你任意触发我只执行最后一次操作
根据上面的定义可以很轻松编写出一个简单的防抖函数
实现
// 第一版
function antiShake(call, time) {
var i = null;
return function() {
clearTimeout(i);
i = setTimeout(call, time);
};
}
this 以及参数
不过这样有一个问题,就是 this 指向不正确以及参数丢失,这里以mousemove
为例,触发函数的时候会有一个MouseEvent
对象,如果打印函数参数会发现为undefined
,下面就来修复一下
// 第二版
function antiShake(call, time) {
var i = null;
return function() {
var that = this;
var rest = arguments;
clearTimeout(i);
i = setTimeout(function() {
call.apply(that, rest);
}, time);
};
}
立即执行
有时候我不想让他等待时间结束在执行,而是一开始就触发
// 第三版
function antiShake(call, time, immediately) {
var i = null;
return function() {
var that = this;
var rest = arguments;
clearTimeout(i);
if (immediately) {
var reversal = !i;
i = setTimeout(function() {
i = null;
}, time);
if (reversal) {
call.apply(that, rest);
}
} else {
i = setTimeout(function() {
call.apply(that, rest);
}, time);
}
};
}
返回值
异步执行的函数我们没办法同步返回他的值,但是对于立即执行的函数,我们应当把值返回
// 第四版
function antiShake(call, time, immediately) {
var i = null;
return function() {
var that = this;
var rest = arguments;
clearTimeout(i);
if (immediately) {
var reversal = !i;
i = setTimeout(function() {
i = null;
}, time);
if (reversal) {
return call.apply(that, rest);
}
} else {
i = setTimeout(function() {
call.apply(that, rest);
}, time);
}
};
}
取消
到这里基本上防抖函数就基本写完了,上述我们用mousemove
事件举例,但是我想当鼠标移开的时候我想取消这个事件,这也是正常的需求,下面就来实现取消功能
function antiShake(call, time, immediately) {
var i = null;
function _private() {
var that = this;
var rest = arguments;
clearTimeout(i);
if (immediately) {
var reversal = !i;
i = setTimeout(function() {
i = null;
}, time);
if (reversal) {
return call.apply(that, rest);
}
} else {
i = setTimeout(function() {
call.apply(that, rest);
}, time);
}
}
_private.cancel = function() {
clearTimeout(i);
i = null;
};
return _private;
}