【JavaScript教程】防抖(二):让大厂面试官惊艳的防抖节流

零 JavaScript教程评论120字数 3525阅读11分45秒阅读模式

防抖:

在JavaScript中,防抖(Debounce)是一种编程技巧,用于控制某些函数的执行频率,以确保它们不会因为连续的触发(如快速连续的用户输入、窗口调整大小等事件)而在短时间内被频繁调用。防抖的主要目的是优化性能,减少不必要的计算和 DOM 操作,从而提高应用程序的响应速度和用户体验。

用效果展示一下:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

所以说,不管你是点击还是怎样的轻微触碰,都会使页面上的数字疯狂增加,这就像是我们在执行我们页面上的按钮操作一样,页面上的效果一直在不间断的加载,也就是短时间内被频繁调用,这就影响了操作和用户体验,从而有了防抖这个概念。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

这里也就是说,dom update < 屏幕更新时间,这就前段问题复杂起来了,在 ajax 发送请求时,耗时的任务 > 触发频率,所以我们在这里来进行前端的性能优化。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

防抖的功能

  1. 提高性能:通过减少不必要的函数调用,降低CPU和内存的使用,尤其是在执行开销较大的函数操作时,如DOM操作、网络请求等,能显著提升应用性能。
  2. 优化用户体验:对于用户输入、窗口大小调整等场景,防抖可以避免因连续快速的操作导致界面卡顿或频繁更新,提供更平滑的用户体验。
  3. 节省资源:对于需要访问外部资源(如服务器API调用)的操作,防抖可以减少不必要的网络请求,节约带宽和服务器资源。
  4. 控制事件响应:在某些情况下,我们可能只关心用户操作的最终状态而非中间过程,比如表单验证、搜索建议的显示,防抖可以帮助我们只在用户停止操作后才执行相应的处理逻辑。
  5. 减少误操作:对于一些敏感操作,防抖可以防止用户因快速连续点击导致的多次执行,如提交按钮的点击。

所以我们最终的目的是:页面的优化,是我们前端性能优化最重要的点。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

使用防抖带来的效果

xml

复制代码
<div id="container"></div>
    <script>
        var count = 1;
        var container = document.getElementById('container');
        // 事件处理函数
        function getUserAction() {

            container.innerHTML = count++;
        }
        
        function debounce (func,wait) {
            // 这就是闭包
            var timeout
            return function() {
                // 事件的执行函数 this -> container
                // 控制执行次
                var context = this
                var args = arguments // 

                clearTimeout(timeout)
                // func this -> 普通函数来运行 window
                timeout = setTimeout(function() {
                    func.apply(context,args)
                },wait)
            }
        }
        
        container.onmousemove = debounce(getUserAction,1000)
    </script>

这段代码是一个完整的HTML文档,演示了如何使用原生JavaScript实现一个具有防抖(debounce)功能的鼠标移动跟踪器。下面是代码的详细解释和组成部分:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

CSS样式

  • 内联样式定义了一个ID选择器(#container),设置了该div的样式属性,如宽度、高度、背景色、字体大小等,使其在页面中突出显示,并且文本居中。

JavaScript脚本

  • 变量初始化:
    • count变量初始化为1,用于存储鼠标移动的次数。
    • container变量通过document.getElementById('container')获取页面上的div元素。
  • 事件处理函数 getUserAction:
    • 每当该函数被调用时,它会更新container的内容为当前的count值,并使count自增1。
  • 防抖函数 debounce:
    • 这是一个高阶函数,接收一个函数func和等待时间wait作为参数。
    • 它返回一个新的函数,该函数在被连续调用时,只有在最后一次调用后的wait毫秒内没有再次被调用时,才会执行传入的func
    • 使用了闭包来保存上一次的计时器引用,确保每次调用都能清除前一次的定时器,防止函数被执行多次。
    • 利用apply(context, args)确保在延迟执行时,func的上下文(this)是正确的,虽然在这个特定的例子中,由于getUserAction内部没有直接使用this,这部分并不关键。
  • 事件绑定:
    • 使用DOM Level 0的方式,将mousemove事件与container元素关联,并将debounce处理后的getUserAction作为事件处理程序。
    • 这意味着当鼠标在container内移动时,getUserAction函数不会立即执行,而是直到鼠标静止超过1000毫秒后,才更新显示计数。

这就展示了如何使用JavaScript和防抖技术来提高性能,避免在短时间内因高频触发的事件(如鼠标移动)导致的不必要的函数执行。通过这种方式,页面能够更加高效地响应用户操作,特别是在执行成本较高的操作时。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

最后需要注意的点是:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

ini

复制代码
 function getUserAction() {

            container.innerHTML = count++;
        }
  1. 事件处理函数的主要目的是更新页面上ID为 container 的元素内容,以反映鼠标移动事件触发的计数,也就是说每当 getUserAction 函数被调用,它就会更新页面上指定 div 的内容,显示自从页面加载以来鼠标在该区域移动的累计次数。

javascript

复制代码
 function debounce (func,wait) {
            // 这就是闭包
            var timeout
            return function() {
                // 事件的执行函数 this -> container
                // 控制执行次
                var context = this
                var args = arguments // 

                clearTimeout(timeout)
                // func this -> 普通函数来运行 window
                timeout = setTimeout(function() {
                    func.apply(context,args)
                },wait)
            }
        }
  1. 在debounce函数下形成了一个function的闭包函数,其能够访问在其外部定义的timeout变量,就使得每次返回的函数实例都有自己的独立timeout
  2. 而在之后的时间执行中,分别保存了上下文参数,清除定时器以及设置了新的定时器。而在设置新的定时器中通过apply的显示绑定调用了func函数,改变了this的指向。

惊艳的防抖效果

xml

复制代码
<body>
    <script>
       
        function debounce(func,wait,immediate) {
            // 自由变量空间
            var timeout ,result
            // 真正执行的函数
            return function() {
                // 二传手
                var context = this
                var args = arguments

                if (timeout) clearTimeout(timeout)
                if (immediate) {
                    var callNow = !timeout
                    timeout = setTimeout(function() {
                        timeout = null
                    },wait)
                    if(callNow) result = func.apply(context,args)
                }else  {
            timeout = setTimeout(function() {
                func.apply(context,args)
            },wait)
        }
        return result
            }
        }
        debounce(getUserAction,1000,true)
    </script>
</body>

bash

复制代码
function debounce(func, wait, immediate) { ... }
  • func: 需要进行防抖处理的实际函数。
  • wait: 防抖的等待时间(毫秒),在此期间若无新的触发,则执行func
  • immediate: 布尔值,决定是否立即执行func至少一次。

这里最主要的区别就是立即执行的逻辑 immediate。就是说:文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

immediatetrue时,检查是否是第一次调用(!timeout),如果是,则立即执行func并记录返回结果到result。同时,设置一个新的定时器,用于重置timeout,确保后续触发不会立即执行。文章源自灵鲨社区-https://www.0s52.com/bcjc/javascriptjc/15338.html

否则,遵循传统的防抖逻辑,仅在最后一次调用后的wait毫秒后执行func

主体思路

防抖功能函数 为了性能优化 1/60 (屏幕刷新率) 若是函数执行时间大于屏幕刷新时间 ——> 则会卡顿

func 是真正要执行的处理函数, this,args权利来指向

wait 定时器 id clear ,最后一次的设定

immediate 立即执行一次

总结:

这里最主要的体现就是性能的优化,也是我们前端最主要的点。 debounce将执行推到最后一次,把之前的触发全部取消来减少执行的次数。

零
  • 转载请务必保留本文链接:https://www.0s52.com/bcjc/javascriptjc/15338.html
    本社区资源仅供用于学习和交流,请勿用于商业用途
    未经允许不得进行转载/复制/分享

发表评论