前端性能优化之 --- 防抖&节流

今天我们的目标是能够手写防抖&节流函数

防抖

概念:触发事件后在 n 秒内函数只能执行一次 如果在 n 秒内又触发了事件 则重新计算函数执行时间

我们什么时候需要防抖函数来优化呢? 高频触发的事件,比如我们会狂点按钮,疯狂移动等

	    // 需要防抖处理
        let box = document.querySelector('.box')
        box.onmousemove = function(e){
            box.innerHTML = e.clientX
        }

我们先来实现一个简版的防抖函数来处理

		// 简单版防抖函数 
		// 出现的问题 上来第一次不执行
        let box = document.querySelector('.box')
        let boxDebounce = debounce(move,1000)
        box.onmousemove = boxDebounce
        function move(e){
            box.innerHTML = e.clientX
        }

        function debounce(fn,wait){
            let timer = null
            return function(){
                let args = arguments
                timer && clearTimeout(timer)
                timer = setTimeout(()=>{
                    fn.apply(this,args)
                },wait)
            }
        }

简单版防抖函数 我们实现了,但是第一次上来根本没有立刻执行,做一下升级

        // 升级版防抖函数 上来第一次执行
        let box = document.querySelector('.box')
        let boxDebounce = debounce(move,1000)
        box.onmousemove = boxDebounce
        function move(e){
            box.innerHTML = e.clientX
        }

        function debounce(fn,wait){
            let timer = null
            return function(){
                let args = arguments
                let now = !timer;
                timer && clearTimeout(timer)
                timer = setTimeout(()=>{
                    timer = null
                },wait)
                // if(now){
                //     fn.apply(this,args)
                // }
                now ? fn.apply(this,args)
                    : ''
            }
        }

自己在设计防抖函数的时候也可以自己在设置一个额外的参数来取代这里的变量now哈

节流

概念:连续触发的事件我们使其一定时间内触发一次
同样用这个box举例

	    let box = document.querySelector('.box')
        let boxReduce = reduce(move,400)
        box.onmousemove = boxReduce
        function move(e){
            box.innerHTML = e.clientX
        }

        function reduce(fn,wait){
            let timer = null
            return function(){
                let args = arguments
                if(!timer){
                timer = setTimeout(()=>{
                    timer = null
                    fn.apply(this,args)
                },wait)
            }
            }
        }

我们在这里只是将timer设置为null,但是并没有清除定时器,看似没什么影响,我们也应该解决的更细致一些,优化它(使用时间戳去替换timer,不用setTimeout)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            background: #00acec;
            height: 500px;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <script>
        let box = document.querySelector('.box')
        let boxReduce = reduce(move,400)
        box.onmousemove = boxReduce
        function move(e){
            box.innerHTML = e.clientX
        }

        // function reduce(fn,wait){
        //     let timer = null
        //     return function(){
        //         let args = arguments
        //         if(!timer){
        //         timer = setTimeout(()=>{
        //             timer = null
        //             fn.apply(this,args)
        //         },wait)
        //     }
        //     }
        // }

        function reduce(fn,wait){
            let last = 0
            return function(){
                let args = arguments
                let now = Date.now()
                if(now - last > wait){
                    fn.apply(this,args)
                    last = now
                }
            }
        }
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值