フロントエンド性能最適化---振れ防止&スロットル


今日の目標は手書きでブレ止め&スロットル関数を作ることです
ブレ止め
コンセプト:イベントがトリガーされた後、n秒以内に関数は1回しか実行できません.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を置き換え、settimoutを使用しません).
<!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>