您现在的位置是:首页 > 正文

js中的函数防抖和函数节流

2024-04-01 00:38:20阅读 1

1、什么是函数防抖和函数节流

    防抖(debounce)和节流(throttle)都是用来控制某个函数在一定时间内执行多少次的技巧,两者相似不相同,基本思想都是某些代码不可以在没有间断的情况下连续重复执行

1.1 函数防抖

如果一个事件被频繁执行多次,并且触发的时间间隔过短,则防抖函数可以使得对应的事件处理函数,只执行最后触发的一次。函数防抖可以把多个顺序的调用合并成一次。

1.2 函数节流

如果一个事件被频繁触发多次,节流函数可以按照固定的频率去执行相应的事件处理方法。函数节流保证一个事件一定事件内只能执行一次。

2、应用

类型 场景
1、搜索框输入(只需要最后一次输入完成后再放松Ajax请求)
函数防抖 2、滚动事件scroll(只需要执行触发后的最后一次滚动事件的处理程序)
3、文本输入的验证(连续输入文字后发送Ajax请求进行验证,停止输入后验证一次)
1、DOM元素的拖拽功能实现(mousemove
函数节流 2、游戏中的刷新率
3、Canvas画笔功能

总的来说,函数防抖适合多次事件一次响应的情况,函数节流适合大量事件按照时间做平均分配触发

3、实现

  3.1 实现函数防抖

function debounce(fn, wait) {
  var timer = null;
    // 返回函数对debounce作用域形成闭包
  return function () {
      var context = this
      var args = arguments
      if (timer) {
          // 事件被触发,清除timer并重新开始计时
          clearTimeout(timer);
          timer = null;
      }
      timer = setTimeout(function () {
          fn.apply(context, args)
      }, wait)
  }
}

var fn = function () {
  console.log('boom')
}

setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次

setInterval(debounce(fn,2000),1000) // 不会触发一次(把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)

1、第一次调用函数的时候创建了一个定时器,在指定的时间之后运行代码

2、当第二次调用该函数的时候,会清除前一次的定时器并设置另一个

3、如果前一个定时器已经执行过了,这个操作就没有任何意义

4、当前一个定时器没有执行的时候,就是将他替换成一个新的定时器

5、目的是只有在执行函数的请求停止了wait时间之后才执行

  3.2 实现函数节流

    1)利用时间戳实现
// fn 是需要执行的函数
// wait 是时间间隔
const throttle = (fn, wait = 50) => {
  // 上一次执行 fn 的时间
  let previous = 0
  // 将 throttle 处理结果当作函数返回
  return function(...args) {
    // 获取当前时间,转换成时间戳,单位毫秒
    let now = +new Date()
    // 将当前时间和上一次执行函数的时间进行对比
    // 大于等待时间就把 previous 设置为当前时间并执行函数 fn
    if (now - previous > wait) {
      previous = now
      fn.apply(this, args)
    }
  }
}

// DEMO
// 执行 throttle 函数返回新函数
const betterFn = throttle(() => console.log('fn 函数执行了'), 1000)
// 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn
setInterval(betterFn, 10)
    2) 利用定时器实现
function throttle(fn, threshold, scope) {
    let timer;
    return function () {
        let context = scope || this, args = arguments;
        if (!timer) {
            timer = setTimeout(function () {
                fn.apply(context, args);
                timer = null;
            }, threshold)
        }
    }
}

4、实例(scroll 事件)

     <!-- CSS样式 -->
    <style>
        .wrap {
            width: 200px;
            height: 330px;
            margin: 50px;
            margin-top: 200px;
            position: relative;
            float: left;
        }

        .header {
            width: 100%;
            height: 30px;
            background-color: #a8d4f4;
            text-align: center;
            line-height: 30px;
        }

        .container {
            background-color: darkseagreen;
            box-sizing: content-box;
            width: 200px;
            height: 300px;
            overflow: scroll;
            position: relative;
        }

        .content {
            width: 140px;
            height: 800px;
            margin: auto;
            background-color: cadetblue;
        }
    </style>

<!-- html -->
<body>
    <div class="wrap">
        <div class="header">滚动事件:普通</div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滚动事件:<strong>加了函数防抖</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
    <div class="wrap">
        <div class="header">滚动事件:<strong>加了函数节流</strong></div>
        <div class="container">
            <div class="content"></div>
        </div>
    </div>
</body>
 let els = document.getElementsByClassName('container');
        let count1 = 0,
            count2 = 0,
            count3 = 0;
        const THRESHOLD = 200;

        els[0].addEventListener('scroll', function handle() {
            console.log('普通滚动事件!count1=', ++count1);
        });
        els[1].addEventListener('scroll', debounce(function handle() {
            console.log('执行滚动事件!(函数防抖) count2=', ++count2);
        }, THRESHOLD));
        els[2].addEventListener('scroll', throttle(function handle() {
            console.log(Date.now(), ', 执行滚动事件!(函数节流) count3=', ++count3);
        }, THRESHOLD));

        // 函数防抖
        function debounce(fn, delay, scope) {
            let timer = null;
            let count = 1;
            return function () {
                let context = scope || this,
                    args = arguments;
                clearTimeout(timer);
                console.log(Date.now(), ", 触发第", count++, "次滚动事件!");
                timer = setTimeout(function () {
                    fn.apply(context, args);
                    console.log(Date.now(), ", 可见只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行!");
                }, delay);
            }
        }

        // 函数节流
        function throttle(fn, threshold, scope) {
            let timer;
            let prev = Date.now();
            return function () {
                let context = scope || this,
                    args = arguments;
                let now = Date.now();
                if (now - prev > threshold) {
                    prev = now;
                    fn.apply(context, args);
                }
            }
        }

运行结果:
![普通](https://img-blog.csdnimg.cn/77feb83f70014316a59cb0ee46ace82c.png#pic_center

函数防抖
在这里插入图片描述

网站文章

  • 极地求生自定义服务器僵尸模式,绝地求生自定义房间使用手册 教你如何玩僵尸模式...

    极地求生自定义服务器僵尸模式,绝地求生自定义房间使用手册 教你如何玩僵尸模式...

    《绝地求生》正式服即将到来自定义服务器功能,而这次是不限号测试。官方今日发布了自定义服务器的使用手册,作为参考资料教大家如何游玩自定义房间的各种功能。此外官方表示,由于自定义服务器的公开是‘不限号测试...

    2024-04-01 00:38:12
  • java的js拼接字符串的注意事项

    对于JS一直有些模糊,熟悉又陌生的感觉,近期在写项目时需要使用到JS拼接字符串,就是用JS的写页面首先,使用js拼接input是要注意使用引号(次引号不是汉语或英语的引号,而是键盘上的tab键上面的哪...

    2024-04-01 00:38:07
  • [CTFhub技能树]SQL注入———整数注入

    [CTFhub技能树]SQL注入———整数注入

    u后面接的URL --batch -dbs就是爆库 -o类似与一键优化运行速度。sqlmap直接运行不了的的 前面加个python 然后是sqlmap.py。然后我就可以开始爆表 -D 后面接指定库名...

    2024-04-01 00:37:43
  • 【python教程入门学习】阿里python面试题之年薪40万

    随着人工智能时代的到来,Python工程师的需求量也在与日俱增。现在,很多知名公司都或多或少的在使用Python。而对于Python工程师来说,进入大公司,是一个新的职业起点。就给大家分享一套阿里巴巴...

    2024-04-01 00:37:37
  • 服务器SSL不安全漏洞修复方案

    服务器SSL不安全漏洞修复方案

    关于SSL POODLE漏洞 POODLE = Padding Oracle On Downgraded Legacy Encryption.是最新安全漏洞(CVE-2014-3566)的代号,俗称“贵宾犬”漏洞。 此漏洞是针对SSL3.0中CBC模式加密算法的一种padding oracle攻击,可以让攻击者获取SSL通信中的部分信息明文,如果将明文中的重要部分获取了,比如cookie,sess

    2024-04-01 00:37:30
  • 索引切片复习

    索引切片复习

    【代码】索引切片复习。

    2024-04-01 00:37:07
  • Linux常见指令(超详解哦)

    Linux常见指令(超详解哦)

    Linux与我们熟悉的Window都是操作系统,我们经常在Window操作系统的图形化界面中进行操作。其中基本的比如创建一个文件夹、在文件夹中放置文件、修改文件名、向文件中写数据、移动文件的位置、查看文件的信息、删除文件等,我们也可以打包压缩文件、解压缩文件。只是在Linux的命令行中,我们需要通过指令来实现这些操作。在本篇文章中就来介绍这些基本指令

    2024-04-01 00:37:00
  • mac 苹果电脑升级系统后蓝牙耳机只有一边有声音 苹果电脑连接耳机音质不好 苹果电脑浏览网页音视频嘈杂

    mac 苹果电脑升级系统后蓝牙耳机只有一边有声音 苹果电脑连接耳机音质不好 苹果电脑浏览网页音视频嘈杂

    环境:电脑系统:耳机:手工定制蓝牙平头耳机 蓝牙模块:高通5141情况说明:升级系统前正常升级系统后蓝牙耳机在连接成功时,双耳都有声音且正常,但是播放音乐时,仅右耳有声音。解决:mac搜索 音频MIDI设置找到输出设备,更改输出格式测试正常本教程到此结束私信博主进入QQ技术交流群~...

    2024-04-01 00:36:54
  • C语言经典题目50题

    【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去       掉不满足...

    2024-04-01 00:36:50
  • linux虚拟网络设备

    见:DPDK(二):准备知识7---linux虚拟网络设备 - 小蚂蚁_CYJ - 博客园

    2024-04-01 00:36:25