手写函数防抖节流

javascript/jquery

浏览数:1,066

2019-1-12

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()
      }
  }
}

原文地址:https://segmentfault.com/a/1190000017860819