函数去抖动和节流

2017年10月03日Web前端0

我们常常会给一些经常触发的事件,比如resize、keyup绑定一些事件,当我们绑定过多或回调函数过于复杂时,往往会影响执行效率。 针对这种情况,我们可以使用去抖动或节流处理。

一、函数去抖动

去抖动,就是限制下次函数调用之前必须等待的时间间隔,换种理解方式的话,就是当调用函数n毫秒后,才会执行该函数,若在这n毫秒内又调用此函数则将重新计算执行时间。

/**
 * 函数去抖动
 * @param {Function} fn 连续被触发的函数
 * @param {Object} context 触发上下文环境
 */
function debounce(fn, context){
    clearTimeout(fn.timer);
    fn.timer = setTimeout(function(){
        fn.apply(context);
    }, 500);
}
// 其他函数
var clickfn = function() {
    console.log(new Date().getTime());
}
document.onclick = function() {
    debounce(clickfn, window);
};

直接看代码,我们默认该函数只能在500ms中调用一次时,才会真正的执行。

原理很简单,设置一个需要延时的计时器,当在规定时间内再次调用时,重置定时器。当然至于延时,我们可以给个参数去设置。

注:fn别是匿名函数,否则会没有去抖动的效果。

考虑到触发时不能传入参数,再次做修改:

function debounce(fn, delay = 0){
    let timer = null;

    return function() {
        var args = [].slice.call(arguments, 0)
        var context = this
        clearTimeout(timer);
    
        timer = setTimeout(function(){
            fn.apply(context, args);
        }, delay);
    }
}

二、函数节流

节流函数只允许一个函数在规定的时间内只执行一次。

它和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

/**
 * 函数节流
 * @param {Function} fn 规定多少秒内必须执行的函数
 * @param {Number} delay 规定的时间
 */
function throttle(fn, delay){
    var timer = null;

    return function(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                fn.apply(context,args);
                timer = null;
            },delay);
        }
    }
}
// 其他函数
var clickfn = function() {
    console.log(new Date().getTime());
}
var callback = throttle(clickfn, 500);
document.onclick = function() {
    callback();
};

利用闭包的性质,当点击时变绑定对应的延时处理函数,且在未执行完成的情况下不再去帮定,实现了节流方式。

注:注意闭包的使用。