相同点:在一段时间之后粗发对应的事件。
区别:防抖会有"延迟",而节流不会有这个特性。
防抖
防抖其实就是一种延迟触发,注意这个延迟,是重点。 假设现在延迟时间为5s,那么当你第一次触发事件之后,会延迟5s,在这5s内,你在此触发事件,有会延迟5s 也就是说,防抖会有"延迟"这个特性。
使用settimeout直接调用事件函数
每次触发事件的时候,清空timer。
使用settimeou直接来触发事件,比较麻烦,因为无法设置回调函数的this和参数,所以这里重写了settimeout
<body>
<button id="mybtn">12313</button>
<script>
function debound(await,handleFn){
// 这里面两个变量是静态变量,存储在debound函数里面
// 如果你用this.ifFrist的话,那么就是对应的局部变量,调用的是当前this里面的变量
// 所以静态变量作用在这里,可以利用闭包向上查找的原理
var ifFrist = false;
var timer = null;// 利用闭包缓存timer
var paramt =
return function () {// 父类传入的参数
// 该函数会被事件触发的时候,由window调用
// this=》window args就是window传入的事件参数了
let context = this;
let args = arguments;
if(!ifFrist){
/**
* 这里为什么用apply,不用call或者bind?
* bind返回一个函数,而且没参数
* call参数传递需要一个一个传入,当然你可以使用{args},但是总不方便
* apply天然适合这个场景
*/
handleFn.apply(context,args);
ifFrist = !ifFrist;
}else{
if(timer==null){
timer = window.setTimeout(handleFn,await,context,args);
}else{
window.clearTimeout(timer);
timer = window.setTimeout(handleFn,await,context,args);
}
}
}
}
let btn = document.getElementById("mybtn");
btn.addEventListener("click",debound(5000,handle));
function handle(a){
console.log("123",this,a);
}
// 重写settimeout
var _st = window.setTimeout;
window.setTimeout = function(fRef, mDelat,content,paramt) {
if(typeof fRef === 'function'){
var f = function(){ fRef.apply(content, paramt); };
return _st(f, mDelat);
}
return _st(fRef,mDelat);
};
</script>
使用settimeout间接调用函数
<body>
<button id="mybtn">12313</button>
<script>
/*
* 不实用settimeout来调用目标函数,避免settimeout带来this无法同步的bug
* @param func
* @param wait
* @returns {Function}
*/
function debounce(Fn,await){
timer = null;
return function () {
var content = this;
var arg = arguments;
// 非null,说明在冷却期,冷却期触发的事件,需要延迟
if(timer){
clearTimeout(timer);
timer = setTimeout(function () {
timer = null;
},await)
}
if(!timer) {
Fn.apply(content, arg);
timer = setTimeout(function () {
timer = null;
},await)
}
}
}
let btn = document.getElementById("mybtn");
btn.addEventListener("click",debounce(handle,2000));
function handle(){
console.log("123",this);
}
</script>
</body>
节流:
假设节流设置为5s,第一次触发之后,5s内触发,不会有响应,但是不会 "延迟"。
<script>
function throttle(Fn,await) {
var perTime = 0;
return function () {
let context = this;
let args = arguments;
let currentTime = Date.now();
if(currentTime-perTime>=await){
Fn.apply(content,args);
perTime = Date.now();
}
}
}
</script>