# 防抖函数debounce

防抖和节流是用来做性能优化,使用的频率比较高。

例如: 滚动事件的监听,往往滚动一下,会触发很多次,这显然是有性能问题的,其实只需要触发一次

防抖思想:在短时间内可能多次触发执行function,但是,实际只需要一次的结果就好,除第一次或最后一次,其他的的触发只会重新计时。

  • 立即执行:第一次触发就执行function,然后启动倒计时,在倒计时内再次触发,不会执行,只会更新倒计时时间。
  • 延迟实行:从第一次触发开始执行倒计时,在倒计时内,再次触发,不会执行,只会更新倒计时时间,倒计时结束 执行function
/**
 * @param func 需要防抖处理的方法
 * @param wait 防抖等待时间
 * @param immediate 是否立即执行
 * 
 * @returns 经防抖处理后方法的引用,可使用cancel提前取消倒计时
*/
function debounce(func, wait, immediate) {

    var timeout, result;

    var debounced = function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        } else {
            timeout = setTimeout(function(){
                result = func.apply(context, args)
            }, wait);
        }
        return result;
    };

    debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
    };

    return debounced;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

注意

在使用cancel方法时

  • immediate: true时,func已执行;
  • immediate: false时,func未执行;

举个例子

function showTop  () {
    const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,1000)
1
2
3
4
5

此时会发现,必须在停止滚动1秒以后,才会打印出滚动条位置。