面试题之防抖和节流的实现

267 阅读3分钟

前言

让我们先介绍防抖是什么,节流是什么?

防抖

防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

节流

节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。

为什么要防抖?

有些时候操作是高频触发的,比如我们的短时间内多次点击登录按钮请求登录,那么我们不应该每次登录都去执行操作,应该只做一就好。在比如监听输入框输入,不应该每次去触发监听,应该是用户完成一段输入后,再进行触发。

注:防抖就是等高频率触发结束后,再进行事件响应,

防抖的实现

当你触发点击事件的时候会开启一个定时器,如果再次触发,则清除上次的定时器。然后重新开启一个定时器,如果一直点击会一直重复这个过程。直到规定的时间内没有触发第二次,则去执行,触发操作,事件响应。

QQ录屏20220306145015 00_00_00-00_00_30.gif

<body>
<button id="btn">
    提交
</button>
<script>
    let btn = document.getElementById('btn')
    btn.addEventListener('click',debounce(a,1000))
    function a(e) { 
        console.log(e);
        console.log(this);
            console.log('提交成功');
    }
</script>
</body>
function debounce(fn, delay) {
    let timer = null 
    return funtion() { // 采用闭包
    clearTimeout(timer) // 清除定时器
    let arg = arguments
    timer = setTimeout(() => {
    fn.call(this, arg) // 防止作用域不清楚
    },delay)
}

为什么要节流?

防抖存在一个问题,事件会一直到等到用户完成操作后一段时间再触发,如果一直操作就不会被触发。如果这只是个按钮,点击就发送请求,如果一直点,那么请求就会一直不发出去。这里的正确思路应该是第一次点击就发送,然后上一个请求回来后,才能再发。

注:节流就是某个操作希望上一次的完成后再进行下一次,或者说在规定的时间内只触发一次

节流的实现

当你触发操作的时候,会开启一个定时器,会有一个time记录触发操作的时间,pre记录上次触发事件的时间,如果 (time - pre > 定时的时间),则事件触发。

QQ录屏20220306145436.gif

<body>
<button id="btn">
    提交
</button>
<script>
    let btn = document.getElementById('btn')
    btn.addEventListener('click',throttle(a,1000))
    function a() { 
     console.log(this);
            console.log('提交成功');
    }
</script>
</body>
function throttle(fn, delay = 1000) {
    let prev = 0
    return function() {
        let time = Date.now() // 当前点击的时间
        let arg = arguments 
        if(time - prev >= delay) {
            fn.apply(this, arg)
            prev = Date.now() // 记录上次结束的时间
        }

    }
}

总结

防抖和节流的相同点

都是为了防止高频率的触发操作,从而浪费性能

防抖和节流区别

防抖是让你多次触发,只生效最后一次。适用于我们只需要一次触发生效的场景。

节流是让你的操作,每隔一段时间才能触发一次。适用于我们多次触发要多次生效的场景。