天天看点

函数节流和函数防抖函数节流和函数防抖

函数节流和函数防抖

函数节流概念: 函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期

比如在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件

<script>

    var n = 0;
    function resizeHandler () {
        console.log(n++);
    }
    window.onresize = resizeHandler
</script>
           

效果随着窗口大小改变不停打印n的值

使用函数节流

<script>
    var n = 0;
    function resizeHandler () {
        console.log(n++)
    }
    function throttle (method, delay) {
        var timer = null;
        return function () {
            var context = this;
            var args = arguments;
            clearTimeout(timer);
            timer = setTimeout(() => {
                method.apply(context, args)
            }, delay);
        }
    }
    window.onresize = throttle(resizeHandler, 500);//因为返回函数句柄,不用包装函数了
</script>
           

窗口大小改变,不断打印n的值,但不要一直打印,500ms内如果没有继续拖动,则打印值

对于函数节流,有如下几个场景:

  • 游戏中的刷新率
  • DOM元素拖拽
  • Canvas画笔功能

函数防抖:函数执行过一次后,在等待某时间段内不能再次执行;在等待时间内触发此函数,则重新计算等待时间

<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时,连续事件触发时,只会在最后一次触发的时候执行回调。

对于函数防抖,有以下几种应用场景:

  • 给按钮加函数防抖防止表单多次提交。
  • 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
  • 判断scroll是否滑到底部,滚动事件+函数防抖

    总的来说,适合多次事件一次响应的情况

欢迎大家点赞和评论,如有不足之处请大神指出,刚入门,请多多指教。

继续阅读