JS函数防抖、节流

一 、什么是函数防抖

  对于短时间内连续触发的事件(onresizescrollmousemove ,mousehover ),触发事件后 n 秒内函数只能执行一次,如果触发事件后 n 秒内又触发了事件,则重新计算函数延执行时间

二、如何解决

   setTimeout 辅助实现,延迟运行需要执行的代码;

三、具体代码

// 防抖 短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。
/**
 * @desc 函数防抖
 * @param fn目标函数
 * @param delay 延迟执行
 * @param {Object} immediate
 */
function debounce(fn, delay, immediate) {
    if(typeof fn != "function") {
        throw new TypeError("fn不是函数")
    }

    let timer;
    return function() {
        var _this = this
        var args = arguments
        if(timer) {
            clearTimeout(timer)
        }

        if(immediate) { // 立即执行(触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数)
            let callnow = !timer
            timer = setTimeout(() => {
                timer = null
            }, delay)
            if(callnow) fn.apply(_this, args)
        } else { // 延迟执行(触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间)
            timer = setTimeout(function() {
                fn.apply(_this, args);
            }, delay)
        }
    }
}

input.addEventListener('keyUp', debounce(() => {
    console.log(input.value)
}, 600))

四、什么是节流

  函数执行一次之后,该函数在指定的时间期限内不再工作,直到过了这段时间才重新生效

五、适用场景

  搜索框搜索输入、改变浏览器窗口大小

六、代码实现

1 // 节流
 2 /**
 3  * @param {Object} 函数节流
 4  * @param {Object} delay
 5  * @param {type} 1 表时间戳版,2 表定时器版
 6  * 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候
 7  */
 8 function throttle(fn, delay, type) {
 9     if (type === 1) {
10         let previous = 0;
11     } else if (type === 2) {
12         let timer;
13     }
14     return function() {
15         var _this = this;
16         var args = arguments;
17         if(type === 1) {
18             let now = Date.now();
19             if (now - previous > delay) {
20                 fn.apply(_this, args)
21                 previous = now
22             }
23         } else if(type === 2) {
24             if(timer) {
25                 return
26             }
27             timer = setTimeout(function() {
28                 fn.apply(fn, args)
30                 timer = null // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
31             }, delay)
32         }
33     }
34 }
35 
36 diva.addEventListener('drgs', throttle((e) => {
37     console.log(e.offsetX, e.offsetY)
38 }, 100))

猜你喜欢

转载自blog.csdn.net/codingLeader/article/details/122963598