函数防抖和函数节流
最近看了很多别人写的东西,也是对这两个优化方法有了一个初步的了解,两个方法都是对事件的触发的频率进行控制
函数防抖(debounce)
函数防抖:一个函数在n秒内只会执行一次,如果在n秒内又触发了该事件,则重新计算函数执行时间。
应用场景:onmousemove事件,搜索框显示相关推荐,不停滑动滚轮连续触发多次滚动事件
<div id="test"></div>
<script>
let test=document.getElementById("test");
let num=0;
test.onmousemove=()=>{
num++;
test.innerHTML=num;
}
</script>
在给div绑定了mousemove事件后,只要鼠标在元素中移动就会触发该事件,事件被频繁的触发导致页面上的数字增加过快。
那么我们这时就可以使用函数防抖来解决这个问题
1.非立即执行:在移动鼠标后,过n秒才会执行mousemove事件,如果在这n秒内鼠标还在移动那么会不停重置n,直到鼠标不在移动再进行n秒判断才会执行.
封装一个函数,参数是你要执行的函数(作为回调函数传进去,放在定时器里n秒后执行)和时间(你设置的“n”秒),在鼠标持续移动的时候不停地删除上个定时器,重新建一个定时器
let test=document.getElementById("test");
let num=0;
// test.onmousemove=()=>{
// num++;
// test.innerHTML=num;
// }
test.onmousemove=debounce(function fun(){
num++;
test.innerHTML=num;
},1000);
//持续触发不执行
function debounce(fun,timer){
let timeout;
return function(){
clearTimeout(timeout);
timeout=setTimeout(()=>{
fun();
},timer)
}
}
效果
就好比电梯在进入人后等一段时间会关门运行,如果在一个人在电梯快关门之前进入那么电梯又会等一段时间在关门运行
2.立即执行:在鼠标移动时立即触发事件,在此次触发后的n秒内不进行触发,如果n秒内鼠标持续移动,那么n的时间重新计算
建立一个布尔类型变量判断是否可以执行目标函数,函数执行后布尔值变为否执行下面的定时器,定时器只负责把判断条件变为是,如果鼠标持续移动那么条件就一直是否不会执行目标函数
let test=document.getElementById("test");
let num=0;
test.onmousemove=debounce(function fun(){
num++;
test.innerHTML=num;
},1000);
//立即执行
function debounce(fun,timer){
let timeout;
let bool=true;
return function(){
clearTimeout(timeout);
if(bool){
fun();
bool=false;
}else{
timeout=setTimeout(()=>{
bool=true;
},timer)
}
}
}
效果:
函数节流(throttle)
函数节流:在连续触发事件时每隔一段时间就会触发一次,减少事件触发频率
let test = document.getElementById("test");
let num = 0;
test.onmousemove = debounce(function fun() {
num++;
test.innerHTML = num;
}, 1000);
//立即执行
function throttle(fun, timer) {
let timeout;
let bool = true;
return function () {
if (bool) {
bool = false;
setTimeout(() => {
fun();
bool = true;
}, timer)
} else {
return;
}
}
}
如果持续触发移动事件,则,把bool的值变成否,建立一个定时器,在这个定时器完成之前bool的值将一直为否,throttle直接return,直到上一个定时器执行并且改变bool的值返回是,才会进行下一次计时。
效果: