js性能优化之节流和防抖|青训营

119 阅读3分钟

在使用js操作dom元素进行交互时,如何提高性能,节约资源是一个绕不开的话题,而节流和防抖这两个十分相像的概念在其中扮演重要的角色。本文将探讨节流和防抖分别是什么,怎样实现,以及案例分析,来提高你对这两种技术的认知~

一、防抖

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会取消上次没执行完的重新计算函数执行时间。这样就可以避免资源重复加载所造成的浪费。

即“单位时间内多次触发只执行最后一次”。

下面用一个案例来分析:鼠标在盒子上移动,每移动一像素盒子上的计数就会加一,导致计数过于敏感。要求使用防抖技术,使得只有在鼠标停止移动500ms后,里面的数字才会变化+1。

1.使用lodash库实现

lodash库是一个高性能的js使用工具库,其中集成了许多js常见数据类型的处理方法,调用lodash库中的_.debounce函数可以高效实现防抖。

_.debounce(fun,[wait=0],[options=])

<style>
        div {
            width: 200px;
            height: 200px;
            background-color: #b58383;
            font-size: 30px;
            text-align: center;
            line-height: 200px;
        }
    </style>
    <div class="box"></div>
    <script src="/js_exercise/lodash.min.js"></script>
    <script>
const box = document.querySelector('.box')
        let i = 1
        function mouseMove() {
            box.innerHTML = i++
        }
        box.addEventListener('mousemove', _.debounce(mouseMove, 500))
        </script>

2.手写防抖函数

也可以模仿上面的_.debounce函数,写一个自己的防抖函数。

  • 利用setTimeout来实现

  • 利用定时器实现,当鼠标滑过,判断有没有定时器,还有就清除,以最后一次滑动为准开启定时器

    ⑥: 如果有定时器,则清除定时器

    ⑦: 否则开启定时器, 在设定时间内,调用函数

const box = document.querySelector('.box')
        let i = 1
        function mouseMove() {
            box.innerHTML = i++
        }
        box.addEventListener('mousemove', debounce(mouseMove, 500))
        function debounce(fn, t) {
            let timer
            //返回一个匿名函数
            return function () {
                if (timer) { clearTimeout(timer) }

                timer = setTimeout(function () {
                    fn()
                }, t)
            }
        }
note:思考为什么要返回一个匿名函数呢?

因为addEventListener里的函数带了小括号,会立即执行一次,因此页面一打开就执行完毕了,鼠标再滑动就不会执行了。而返回一个匿名函数就使得debounce(mouseMove, 500)=function,就不会再立即执行了。

二、节流

实现单位时间之内 只能触发一次鼠标移动事件

类似于技能冷却时间,触发一次后,在规定时间内再触发就无效了。

1.lodash节流函数

_.throttle(fun[,wait=0],[options=])

500ms之内mouseMove函数只能调用一次

 const box = document.querySelector('.box')
        let i = 1
        function mouseMove() {
            box.innerHTML = i++
        }
        box.addEventListener('mousemove', _.throttle(mouseMove, 500))

2.手写节流函数

  const box = document.querySelector('.box')
        let i = 1
        function mouseMove() {
            box.innerHTML = i++
        }
        box.addEventListener('mousemove', throttle(mouseMove, 500))

        function throttle(fn, t) {
            let timer
            //返回一个匿名函数
            return function () {
                if (!timer) {
                    timer = setTimeout(function () {
                        fn()
                        //清空定时器,注意这个清除方式
                        timer = null
                    }, t)
                }
            }
        }
note:clearTimeout不能在定时器的回调function函数里调用来关闭自己

因此我们使用了赋值方法,timer=null来清除计时器!

三、二者的使用场景

1.‘防抖’

顾名思义,就是防止用户操作时发生抖动,从而触发非必要的多次事件。因此用在‘连续的事件’上,例如:

  • 搜索框输入:设定需用户最后一次输入完毕一定时间后再向后台发送请求
  • 计算窗口大小从而渲染页面:在窗口大小停止变化一定时间后再计算和渲染
  • 输入表单是否合法的检测:

2.‘节流’

用于限定开销较大的情况,避免资源刷新过快。例如:

  • 加载更多:一定时间内只能加载资源一次
  • 滚动条滚动:

以上就是对这两种技术的介绍了~他们的实际应用场景和实现方法并非是固定不变的,需要具体分析想要的效果,再来选择和编码。这也体现了计算机算法的灵活性,作为一门‘人’发明的学科,它的规则是不断在进步的。提醒小伙伴们学习时一定要多多思考,拒绝生搬硬套!