1. 程式人生 > >手寫函式防抖節流

手寫函式防抖節流

DOM 0級事件


<style>
    .demo{width:200px;height:200px;border:1px solid red;overflow-y:scroll;margin-top:50px;}
    .scroll{height:5000px;}
</style>
</head>
<body>
    <div class="wrap">
        <div id="nothing" class="demo">
            普通滾動
            <div class="scroll"></div>
        </div>
        <div id="throttle" class="demo">
            函式節流
            <div class="scroll"></div>
        </div>
        <div id="debounce" class="demo">
            函式防抖
            <div class="scroll"></div>
        </div>
    </div>
    <script type="text/javascript">
        // 普通滾動
        document.getElementById("nothing").onscroll = function(){
            console.log("普通滾動");
        };

        // 函式節流
        var canRun = true;
        document.getElementById("throttle").onscroll = function(){
            if(!canRun){
                // 判斷是否已空閒,如果在執行中,則直接return
                return;
            }

            canRun = false;
            setTimeout(function(){
                console.log("函式節流");
                canRun = true;
            }, 300);
        };

        // 函式防抖
        var timer = false;
        document.getElementById("debounce").onscroll = function(){
            clearTimeout(timer); // 清除未執行的程式碼,重置回初始化狀態

            timer = setTimeout(function(){
                console.log("函式防抖");
            }, 300);
        };            
    </script>
</body>
</html>

DOM 2級事件 事件監聽


document.addEventListener('scroll', debounce(test, 300))

function test() {
    console.log('函式...')
}

函式防抖(debounce)


function debounce(fn, delay) {
    let timer;
    return function() {
        let context = this;
        let args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn.apply(context, args);
        }, delay);
    };
}

函式節流(throttle)


// 方法一:定時器實現
const throttle = function(fn,delay) {
  let timer = null
  return function() {
    const context = this
    let args = arguments
    if(!timer) {
      timer = setTimeout(() => {
        fn.apply(context,args) 
        clearTimeout(timer) 
        timer = null;
      },delay)
    }
  }
}

// 方法二:時間戳
const throttle2 = function(fn, delay) {
  let preTime = Date.now()

  return function() {
      const context = this
      let args = arguments
      let doTime = Date.now()
      if (doTime - preTime >= delay) {
          fn.apply(context, args)
          preTime = Date.now()
      }
  }
}

javascript函式防抖Debounce

來源:https://segmentfault.com/a/1190000017860819