防抖:用户触发事件过于频繁,只需要执行最后一次
场景:在oninput事件中,每按下一次键盘就会触发一次事件,当有请求数据的代码时,会严重影响执行性能,因此采取定时器,控制触发事件的频率,只在经过500ms后触发一次oninput事件
<input type="text" />
<script>
let inp = document.querySelector("input");
let t =null
inp.oninput = function(){
if(t!==null){
clearTimeout(t)
}
t=setTimeout(()=>{
console.log(this.value)
},500)
}
</script>
因为t还处于全局,存在全局污染,所以通过函数进行封装,封装过程用到内层和外层函数(也就是闭包函数)
事件oninput直接绑定防抖(debounce)函数,调用函数部分有两个参数一个是函数,一个是时间,在debounce函数中定义t 并return条件函数。
特别强调:定时器内调用fn函数,因其作用域是window,所以在调用debouce函数时,打印出的this是window。因此需要用call(this)改变this指向。
<script>
inp.oninput = debounce(function () {
console.log(this.value);
//直接调用fn() this指向window
}, 500);
function debounce(fn, delay) {
let t = null;
return function () {
if (t !== null) {
clearTimeout(t);
}
t = setTimeout(() => {
fn.call(this);
// 通过call改变this指向
// fn()
}, delay);
};
}
</script>
节流:控制高频时间的执行次数
场景:在onscroll事件中频繁触发事件,可以通过定时器控制触发次数
<script>
let flag=true
window.onscroll=function(){
if(flag){
setTimeout(()=>{
console.log('ssss')
flag=true
},500)
}
flag =false
}
</script>
同样的道理,因为有全局变量,需要进行封装
<script>
window.onscroll = throttle(function () {
console.log("ddddd");
}, 500);
function throttle(fn, delay) {
let flag = true;
return function () {
if (flag) {
setTimeout(() => {
fn.call(this);
flag = true;
}, delay);
}
flag = false;
};
}
</script>