极简实现系列——手写防抖debounce函数

310 阅读2分钟

极简实现系列 是用最简单的代码实现一些常见的方法,目的是为了帮助理解原理,所以并没有考虑太多限制条件


 防抖函数在日常中还是经常用到的。实现的原理也非常简单,就是利用setTimeout给需要防抖的方法一个延时执行,每次调用的时候重置setTimeout

知道原理后很要很容易的写出一个极简版

    let timer = null
    function debounce(fn, delay) { // fn: 需要防抖的函数,delay:延迟的时间
        clearTimeout(timer)
        timer = setTimeout(fn, delay)
    }

我们来测试一下,写一个input输入框和一个测试函数,input每次输入的时候都打印一个1

<input type="text" id="input">
 
<script>
    function test() {
        console.log(1)
    }
    document.querySelector('#input').addEventListener('input', () => {
       test()
    })
</script>

加上刚才写的防抖函数试试:

<input type="text" id="input">
 
<script>
    let timer = null
    function debounce(fn, delay) {
        clearTimeout(timer)
        timer = setTimeout(fn, delay)
    }
 
    function test() {
        console.log(1)
    }
 
    document.querySelector('#input').addEventListener('input', () => {
       debounce(test, 1000)
    })
</script>

会在停止输入后过一秒才打印1 

看来极简版的防抖函数成功了~~

当然,这样是没什么问题,但是在实际中使用的话还可以再优化下,比如timer这个变量我们定义成全局的,这样有可能会造成污染,还有如果test函数有参数的话,极简版是没办法做到传参数的。我们再来稍微优化一下

优化版:

 

    function debounce(fn, delay) {
        let that = this // 获取上下文
        let timer = null // 利用闭包,避免污染
        return function() {
            let args = arguments // 获取当前参数
            if(timer) {
                clearTimeout(timer)
            }
            timer = setTimeout(() => {
                fn.apply(that, args)
            }, delay)
        }
    }
    function test(e) {
        console.log(e)
    }
    let debounceTest = debounce(test, 1000) // debounce返回一个函数
    document.querySelector('#input').addEventListener('input', (e) => {
        // test()
        debounceTest(e.target.value)
    })

完事~