Js中的防抖和节流实现

58 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

防抖和节流的定义

什么是防抖?

  • 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间;

  • 当事件密集触发时,函数的触发会被频繁的推迟;

  • 只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

总结来说就是:只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数。

什么是节流

  • 当事件触发时,会执行这个事件的响应函数;

  • 如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数;

  • 不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的;

总结来说:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

应用场景

防抖应用场景

  1. 输入框中频繁的输入内容,搜索或者提交信息;

    如果这里不做防抖处理,那么输入一个信息,就会马上提交查询,就造成频繁的发送了很多请求,增大了服务器压力。

  2. 频繁的点击按钮,触发某个事件;

    点击按钮一般用来做提交表单,提交数据的操作,如果没有防抖那么也同样的发送了N多不必要的请求。

  3. 监听浏览器滚动事件,完成某些特定操作;

  4. 用户缩放浏览器的resize事件;

节流应用场景

  1. 监听页面的滚动事件;

  2. 鼠标移动事件;

    鼠标移动事件会不停的触发,来响应做一些操作,那么我们不应该让他一直触发,这样太影响性能,这时候依赖节流就可以避免过于频繁的操作。

  3. 用户频繁点击按钮操作;

  4. 游戏中的一些设计;

    比如飞机大战的游戏中会有这样的设定,即使按下的频率非常快,子弹也会保持一定的频率来发射; 比如1秒钟只能发射一次,即使用户在这1秒钟按下了10次,子弹会保持发射一颗的频率来发射;但是事件是触发了10次的,响应的函数只触发了一次。

防抖和节流的实现

防抖实现

使用了闭包和call函数来实现

//防抖函数
    function debounce(fn,delay){
        let time = null;// 创建一个标记用来存放定时器的返回值

        return function(){
         // 每当用户输入的时候把前一个 setTimeout clear 掉
            if(time !== null){
                clearTimeout(time)
            }
// 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
            time = setTimeout(()=>{
                fn.call(this,arguments);
            },delay)
        }
    }

节流实现

  //节流函数:n段时间内只执行第一次
    function throttle(fn,delay){
        let flag = true;// 通过闭包保存一个标记
    
          return function(){
             // 在函数开头判断标记是否为true,不为true则return
            if (!flag) return;
            // 立即设置为false
            flag = false;
            // 将外部传入的函数的执行放在setTimeout中
            setTimeout(() => { 
            // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
            // 当定时器没有执行的时候标记永远是false,在开头被return掉
                fn.apply(this, arguments);
                flag = true;
            }, delay);
        }
    }


总结

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。 而函数防抖只是在最后一次事件后才触发一次函数,同时掌握好闭包和call函数能帮我们更好理解和实现。