js之防抖函数

js之防抖函数防抖防抖原理事件响应函数在一段时间后才执行 如果这段时间内再次调用 则重新计算执行时间也就是说 在这个时间内 无论你怎么触发事件 我都不会执行 只有这段时间无操作后才会执行 例如 假如防抖设置为 3 秒第一次执行事件后 开始倒计时 3 秒然后等到还剩余 1 秒时 再次触发了事件重新倒计时 从三秒开始这样第一次到第二次触发事件就经历了 5 秒 极大的减轻了服务器的压力先来认识防抖函数的使用 防抖函数实际上已经封装好了 我们只需要用 cdn 引入就可以进行使用了 但是我们依然要明白其中的原理 D

防抖

防抖原理

事件响应函数在一段时间后才执行,如果这段时间内再次调用,则重新计算执行时间

也就是说,在这个时间内,无论你怎么触发事件,我都不会执行,只有这段时间无操作后才会执行!

例如:

假如防抖设置为3秒

第一次执行事件后,开始倒计时3秒

然后等到还剩余1秒时,再次触发了事件

重新倒计时,从三秒开始

这样第一次到第二次触发事件就经历了5秒,极大的减轻了服务器的压力

 <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document 
     title> <style> #container { 
      width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; background-size: 30px; }  
      style>  
       head> <body> <div id="container"> 
        div> <script src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.11.0/underscore.js"> 
         script> <script src="./debounce.js"> 
          script> <script> let count = 0; // 展示事件频繁发生 let container = document.querySelector('#container'); function doSomething(e) { // event console.log(e); console.log(this) // 这里可能是回调或者是ajax请求 // 这里做个示例 container.innerHTML = count++ } // !无防抖,数字会不停的增加,相当于不断的发送请求 // container.onmousemove = doSomething; // 使用防抖,300ms内不会重复发出请求 container.onmousemove = _.debounce(doSomething, 300); 

在这里插入图片描述

这样鼠标滑过的话,就会不断的触发事件,不停的发送请求,会给服务器带来极大的压力

针对这种问题,防抖节流的重要性就来了,它们可以降低函数的触发频率,提高性能,避免资源浪费

手动实现防抖函数

明白其原理之后,我们就可以慢慢实现一个防抖函数

定义一个debounce.js文件

//简单构造出防抖大致框架 //func 要执行的函数,wait要等待的时间 function debounce(func, wait) { 
    let timeout; return function () { 
    // 清空定时器 if(timeout) clearTimeout(timeout); timeout = setTimeout(func, wait) } } 
container.onmousemove = debounce(doSomething, 300) 

结果:

在这里插入图片描述

很明显,此时防抖函数已经起作用啦,但这是可以从控制台看到打印了一些东西\

这就是我们接下来要解决的问题啦

function doSomething(e) { 
    // event console.log(e); //MouseEvent console.log(this) //window // 这里可能是回调或者是ajax请求 // 这里做个示例 container.innerHTML = count++ } 
function debounce(func, wait) { 
    let timeout; return function () { 
    // console.log(this); //=>从中可以测试出this指向的container //保存this let _this = this; // 清空定时器 if(timeout) clearTimeout(timeout); timeout = setTimeout(function () { 
    // console.log(this) //=>这里面的this指向window,也就是前面的count那的this是指向window //但是防抖函数的this应该是指向container func.apply(_this); }, wait) } } 

event的问题:事件处理函数有event对象,然后在测试中,e却是undefined,所以我们需要修正它为mouseEvennt

function doSomething(e) { 
    // event console.log(e); //undefined console.log(this) //window container.innerHTML = count++ } 

修改:

function debounce(func, wait) { 
    let timeout; return function () { 
    // console.log(this); //=>从中可以测试出this指向的container //保存this let _this = this; // 解决前面的event指向问题 let args = arguments; // 清空上从定时器 clearTimeout(timeout); timeout = setTimeout(function () { 
    // console.log(this) //=>这里面的this指向window,也就是前面的count那的this是指向window //但是防抖函数的this应该是指向container func.apply(_this, args); }, wait) } } 

这样,再次测试,event已经是指向mouseEvent了.这和防抖的源码已经相同啦,这时已经可以解决大多数问题了!

防抖完善优化

原生防抖中会存在第三个参数,true,表示立即执行,而我们此次的目的,就是完善这个功能!

debounce(doAnother, 300,true) 

当然,只靠说你可能不太清楚,那么我们来完善一下

function debounce(func, wait, immediate) { 
    let timeout; return function () { 
    // console.log(this); //=>从中可以测试出this指向的container //保存this let _this = this; // 解决前面的event指向问题 let args = arguments; // 清空上从定时器 if(timeout) clearTimeout(timeout); if (immediate) { 
    //若执行过了,不再执行 let callNow = !timeout; //callNow起始值为true,timeout刚开始为undefined,则作取反操作,那么就可以保证callNow初始值为true. timeout = setTimeout(() => { 
    timeout = null; //在wait内,timeout是一个id数字,在在此期间callNow为false,func函数不会执行! }, wait); //初始为true会直接执行,在wait时间之内,callNow设置为timeout有值,则callNow为false,此时不执行,在wait时间之后,timeout设置为null,此时callNow为true开始执行 if (callNow) func.apply(_this, args); } else { 
    timeout = setTimeout(function () { 
    // console.log(this) //=>这里面的this指向window,也就是前面的count那的this是指向window //但是防抖函数的this应该是指向container func.apply(_this, args); }, wait) } } } 

这样,我们的立刻执行防抖就完善好了,可以亲自动手尝试一下

代码优化以及添加取消防抖功能

 function debounce(func, wait, immediate) { 
    let timeout, result; // 检查func是否为函数 if (typeof func !== 'function') { 
    throw new TypeError('Expected a function'); } // wait如果忘记设置,,默认为0 wait = wait || 0; var debounced = function () { 
    // console.log(this); //=>从中可以测试出this指向的container //保存this let _this = this; // 解决前面的event指向问题 let args = arguments; // 清空上从定时器 if (timeout) clearTimeout(timeout); if (immediate) { 
    let callNow = !timeout; timeout = setTimeout(() => { 
    timeout = null; }, wait); if (callNow) result = func.apply(_this, args); } else { 
    timeout = setTimeout(function () { 
    // console.log(this) //=>这里面的this指向window,也就是前面的count那的this是指向window //但是防抖函数的this应该是指向container func.apply(_this, args); }, wait) } return result; } //添加取消防抖函数功能 debounced.cannel = function () { 
    clearTimeout(timeout); timeout = null; } return debounced; } 

防抖函数常见应用

  1. scroll事件的滚动触发
  2. 搜索框输入查询
  3. 表单验证
  4. 按钮提交事件
  5. 浏览器`窗口缩放,resize事件

最后

完整代码以及示例已上传GIthub,里面还有其他的js,vue等等的相关知识,有兴趣的朋友可以去瞧瞧!

下一篇:js之节流函数

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221175.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午6:45
下一篇 2026年3月17日 下午6:45


相关推荐

  • 八卦时钟代码

    八卦时钟代码<!DOCTYPEhtml><htmllang=”en”><head><metacharset=”UTF-8″><title>www.dupengfei.top</title><style>html{background:#000;color:#666;font-size:12px;…

    2022年6月28日
    47
  • 计算机操作系统-操作系统的定义

    计算机系统的层次结构 用户 应用程序 操作系统 纯硬件:CPU、RAM、ROM 其中,操作系统:从操作系统层往两侧看:负责管理协调硬件、软件等计算机资源的工作 从上往下看:为上层的应用程序和用户提供简单易用的服务 从下往上看:操作系统系统软件,而不是硬件定义OperatingSystem是指控制和管理整个计算机系统的硬件和软件资源,并合理地组…

    2022年4月13日
    49
  • python 两个list 求交集,并集,差集

    python 两个list 求交集,并集,差集在python中,数组可以用list来表示。如果有两个数组,分别要求交集,并集与差集,怎么实现比较方便呢?当然最容易想到的是对两个数组做循环,即写两个for循环来实现。这种写法大部分同学应该都会,而且也没有太多的技术含量,本博主就不解释了。这里给大家使用更为装bility的一些方法。老规矩,talkischeap,showmethecode#!/usr/bin/envpython#

    2022年6月21日
    29
  • Android listView长按删除

    Android listView长按删除AndroidlistView长按删除

    2022年7月22日
    23
  • pycharm安装包报错

    pycharm安装包报错  相信有很多Python初学者在使用pycharm安装一些包时会遇到报错现象!  我也是一名Python初学者,当然也会遇到这种问题!当遇到上述问题时,我个人觉得是因为“pip”的版本问题,所以大家可以先更新“pip”(通过cmd更新:python-mpipinstall–upgradepip)。   …

    2022年5月16日
    43
  • createfont函数_windows程序设计基于.net平台

    createfont函数_windows程序设计基于.net平台CFont * f; f = new CFont; f->CreateFont(10, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_BOLD, // nWeight FALSE, // bItalic …

    2022年8月18日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号