防抖节流

287 阅读1分钟

防抖:

当事件持续触发时,只调用一次事件处理函数,一定时间内事件不再触发,再次触发时才会执行;

应用场景:

1、输入框发送ajax请求;
2、窗口缩放、滚动(resize/scroll)时触发

实现:

每次触发事件都要取消之前的延时器(setTimeout)

function debounce(fn,wait){
    let timer=null;
    return function(){
        const that=this;
        const args=arguments;
        if(timer){
            clearTimeout(timer);
        }
        timer=setTimeout(function(){
            fn.apply(that,args)
        },wait);
        
    }
}
function handler(){console.log("防抖")};
window.addEventListener("scroll",debounce(handler,1000));

非立即执行

function debounce(fn,delay) {
    let timer = null;
    return function() {
        let that = this;
        let args = arguments;
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function(){
            fn.apply(that,args)
        },delay)
        // 可以写成箭头函数自动继承this
        // timer = setTimeout(() => {
        //     fn.apply(that, args);
        // }, delay)
    }
}
var clickResult = function() {
    console.log("debounce!");
};
var debounceBtn = function() {
    $("#debounce").click(debounce(clickResult,500))
};
debounceBtn();

立即执行

function debounce(fn,wait) {
    let timer=null;
    return function(){
        let that=this;
        let args=arguments;
        if(timer){
            clearTimeout(timer);
        }
        let callNow = !timer;
        if(callNow){
            fn.apply(that, args)
        }
        timer=setTimeout(function(){
            timer = null;
        },wait);
    }
}
var clickResult = function() {
    console.log("debounce!");
};
var debounceBtn = function() {
    $("#debounce").click(debounce(clickResult,500))
};
debounceBtn();

节流:

当事件持续触发时,使其在一定时间内执行一次事件处理函数。

应用场景:

1、多次点击按钮,实现n秒内生效一次;
2、获取鼠标移动的距离(mousemove);
3、监听滚动事件(scroll);
4、DOM元素的拖拽(mousemove);

实现

每次事件触发时,都要判断当前是否有延时函数。

setTimeout

function throttle(fn,wait){
    let timer=null;
    return function(){
        let that=this;
        let args=arguments;
        if(!timer){
            timer=setTimeout(function(){
                fn.apply(that,args);
                timer=null;
            },wait)
        }
    }
}

时间戳

function throttle(fn,wait){
    let prev=Date.now();
    return function(){
        let that=this;
        let args=arguments;
        let now=Date.now();
        if(now-prev>=wait){
            fn.apply(this,args);
            prev=Date.now();
        }
    }
}

例子:

<button type="button" id="clickF">节流</button>
function throttle(fn,wait){
    var timer=null;
    return function(){
        var that=this;
        var args=arguments;
        if(!timer){
            timer=setTimeout(function(){
                fn.apply(that,args);
                timer=null;
            },wait)
        }
    }
}
function clickFun() {
    console.log("hhhhh");
}
document.getElementById('clickF').addEventListener("click",throttle(clickFun,1000),false);
document.getElementById('clickF').onclick=throttle(clickFun,1000);