js函数防抖

场景

每次resize/scroll触发统计事件
文本输入验证(连续输入文字后发生AJAX请求进行验证,验证一次就好)
加载更多

函数防抖

概念以及原理:
函数执行一次过后,在设置好的一段时间内不在执行;
如果在等待时间内手动触发该函数,那么将重新计算等待时间。
加深概念:
坐电梯,众所周知我们进电梯需要等几秒电梯门才会自动关闭,如果在等待这几秒又有人进来了,那么等待的时候就会重新计算,当然排除我们手动关闭电梯的情况

代码实现(滚动条滚动案例)

<script>
    var n = 0;
    function debounce (method, wait) {
        var timer = null;
        var context, args;
        return function () {
            context = this;
            args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function () {
                method.apply(context, args)
            }, wait)
        }
    }
    window.onscroll = debounce (function () {
        console.log(1)
    }, 500)
</script>

结果:**只会在最后一次触发的时候执行回调,**因为每次调用,都会通过clearTimeout清除掉上一个timer。
思考:这个封装似乎有点问题,如果我想在第一次触发的时候执行回调呢?这种场景适不适合加载更多场景?因为从体验上看,我们希望第一次触发加载更多的时候,就执行回调。而不是在最后一次触发执行回调。如果我们一直滚动页面那么将一直不会触发回调,只有停止滚动才会触发……这样体验就太糟糕了。
代码优化:
基于上面的问题,我们进行再一次封装,多加一个参数。
现假设函数的定义形式为:

<script>
    var n = 0;
    function debounce (method, wait, flag) {
        var timer = null;
        var context, args, result, timestamp;
        var later = function () {
            var oDate = new Date();
            var last = oDate.getTime() - timestamp; // 计算第一次时间戳与当前时间戳的差值。
            if (last < wait && last >= 0 ) { // 在等待时间内触发此函数,重新计时。
                timer = setTimeout(later, wait - last);
            } else {
                timer = null;
                if (!flag) { // 限制flag 为true时,执行回调函数。
                    result = method.apply(context, args);
                    if (!timer) {
                        context = args = null
                    }
                }
            }
        }

        return function () {
            var oDate = new Date();
            var callNow = flag && !timer; // 代表第一次调用立即执行。

            timestamp = oDate.getTime(); // 记录下当前时间戳
            context = this;
            args = arguments;
            if (!timer) { // 第一次触发时,timer为空,进入此分支
                timer = setTimeout(later, wait);
            }
            if (callNow) { // 第一次触发且flag为true,进入此分支
                result = method.apply(context, args);
                context = args = null
            }
            return result;
        }
    }
    window.onscroll = debounce (function () {
        console.log(1)
    }, 500, false)
</script>

此次封装支持两种形式:
flag为true时,连续事件触发时,只会在第一次触发的时候执行回调。
flag为false时,连续事件触发时,只会在最后一次触发的时候执行回调。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值