工具函数系列-防抖debounce

防抖的原理:触发事件,但在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,那就以新的事件时间为准,n 秒后才执行。总之,就是要等触发完事件 n 秒内不再触发事件,才执行。

应用场景input输入

实现

function debounce(func, wait, immediate) {
    var timeout = null, result;
    return function() {
        var context = this; // 修改this指向,避免指向window
        var args = argumenets; // 传参
        
		if (timeout) clearTimeout(timeout); // 等触发完事件n秒后执行
        if (immediate) { // 立即执行第一次 immediate判断是否立即执行
            // 如果已经执行过,不再执行
            var callNow = !timeout; // !null = true   !12 = false
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)
            if (callNow) { // 第一次执行
                result = func.apply(context, args)
            }
        } else {
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)    
        }
        return result; // 只有立即执行模式才能返回结果
    }
}

添加取消模式

比如说我 debounce 的时间间隔是 10 秒钟,immediate 为 true,这样的话,我只有等 10 秒后才能重新触发事件,现在我希望有一个按钮,点击后,取消防抖,这样我再去触发,就可以又立刻执行了

function debounce(func, wait, immediate) {
    var timeout = null, result;
    var debocunced = function() {
        var context = this;
        var args = arguments;
        
        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)
            result = callNow ? func.apply(context, args) : undefined;
        } else {
            timeout = setTimeout(function() {
                func.apply(context, args)
            }, wait)
        }
        return result;
    }
    debounced.cancel = function() {
        clearTimeout(timeout)
        timeout = null
    }
    return debounced;
}

参考文章:https://github.com/mqyqingfeng/Blog/issues/22

测试

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
    <title>debounce</title>
    <style>
        #container{
            width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <script>
        var count = 1;
        var container = document.getElementById('container');

        function getUserAction() {
            let num = count++
            container.innerHTML = num;
            console.log(Date.now(), num)
        };

        container.onmousemove = debounce(getUserAction, 1000);

        // function debounce()...
    </script>
</body>

</html>