防抖和节流

防抖(debounce) 和节流(hrottle)平时只是听说用来防止重复操作的问题,具体也还没使用过,在这里做笔记咯。

防抖(debounce)

防抖是指触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间

效果: 如果短时间内大量触发同一事件,只会执行一次函数。

使用情况:适用于表单输入内容的验证和页面resize事件需要根据最终呈现的页面情况进行dom渲染和表单的多次提交等频繁操作。

思路:使用setTimeout实现计时,只要事件触发,就使用clearTimeout清除上一个计时器,直到规定时间停止触发后,才会执行回调函数。

分析:

1、立即执行: 触发事件后函数会立即执行,如果n秒内不触发事件才能继续执行函数。

2、非立即执行: 触发事件后函数不会立即执行,而是在n秒后执行,如果在n秒内又触发了事件,则会重新计算函数执行时间。

实现:

/**
     * @dec 函数防抖
     * @param func 执行函数
     * @param wait 延迟执行函数时间
     * @param immediate 是否立即执行,true表立即执行,false表非立即执行
     */
    function debounce(func, wait, immediate) {
        let timeout;
        return function () {
            let context = this;
            if(timeout) clearTimeout(timeout);
            if(immediate) {
                var callnow = !timeout;
                timeout = setTimeout(() => {
                   timeout = null; //作为开关变量;且作为闭包引用的变量,手动置为null让其脱离执行环境
                }, wait);
                if(callnow) func.apply(context, arguments);
            } else {
                timeout = setTimeout(() => {
                    func.apply(context, arguments);
                }, wait);
            }
        }
    }

节流(throttle)

节流是指高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率.

效果: 如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效.

思路:使用setTimeout来做一个简单的实现,加上一个状态位来表示当前函数是否处于工作状态:

分析:

1、定时器:在持续触发事件的过程中,函数不会立即执行,而是n秒执行一次,在停止触发后,函数还会执行一次。

2、时间戳: 在持续触发事件的过程中,函数会立即执行,而是n秒执行一次。

/**
     * @dec 函数节流
     * @param func 执行函数
     * @param wait 延迟执行函数时间
     * @param type 1表时间戳,2表定时器
     */
    function throttle(func, wait, type) {
       if(type === 1) {
           let previous = 0;
       } else if(type === 2) {
           let timeout;
       }
       return function () {
           let context = this;
           if(type === 1) {
                let now = Date.now();
                if(now - previous > wait) {
                    func.apply(context, arguments);
                    previous = now;
                }
           } else if(type === 2) {
                if(!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null;
                        func.apply(context, arguments)
                    }, wait);
                }
           }
       }
    }

区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。