防抖和节流相关知识整理

场景1:在滚动事件中做复杂计算;场景2:实现一个预防二次点击操作的按钮;
这些需求都可以通过函数防抖来实现,尤其是第一个需求,如果在频繁的事件回调中做复杂计算,很有可能导致页面卡顿,不如将多次计算合并为一次,只在一个精确点做操作。
防抖和节流的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖情况下只会调用一次,而节流的情况下会每隔一段时间(参数wait)调用一次。
防抖的定义:触发高频事件后n秒内函数只执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
实现的思路:每次触发事件时都取消之前的延时调用方法。

function debounce(fn){
let timeout = null;//创建一个标记来存放定时器的返回值
return function(){
    clearTimeout(timeout);//每当用户输入的时候把前一个setTimeout清除掉
    timeout = setTimeout(()=>{
        //然后又创建一个新的setTimeout,这样就能保证输入字符后的间隔时间内如果还有字符字符要输入的话,就不会执行函数
        fn.apply(this,arguments)
    },500);
};
}
function sayHi(){console.log("防抖成功");}
var inp = document.getElementById("inp");
inp.addEventListener("input",debounce(sayHi))//添加防抖事件`

节流的定义:高频事件触发,但在n秒内只会执行一次,将多次执行变成每隔一段时间执行,节流会稀释函数的执行频率。
实现的思路:每次触发事件时都判断当前是否有等待执行的延时函数。

function throttle(fn){
let canRun = true;//通过闭包保存一个标记,表示开关的状态,初始值为打开
return function(){
    if(canRun){//刚开始检查开关状态,如果是true则表示可以单击
        canRun = false;//此时,立即将开关设置为flase
        setTimeOut(()=>{
            //将外部传入的函数放在setTimeOut中执行
            fn.apply(this,arguments);
            //最后在setTimeOut执行完毕后,再将开关打开,表示可以执行下一次循环。
            //当定时器没有执行的时候,开关标记永远是false,在开头被return掉
            canRun = true;
        },500);
    }
};
}
function sayHi(e){
console.log(e.target.innerWidth,e.target.innerHeight);
}
window.addEventListener("resize",throttle(sayHi));