阅读 53

聊聊JavaScript节流吧

这是我参与更文挑战的第21天,活动详情查看: 更文挑战

什么是节流?

想必大家对一个成员是不陌生的:开源节流,那么节流函数为什么叫节流呢?

因为流量太大了,所以控制一下,隔一段时间放一些,隔一段时间放一些,就节流了。

所以节流函数,就是隔一段时间执行一次,否则的话,就拒绝执行,节省开支。

节省开支这一点,也是节流函数在性能优化中,很重要的存在依据,毕竟性能优化的前提就是节能性能消耗的同时,不影响用户体验。

所以赶快学起来吧。

通用简单版

function throttle(func, wait) {
    var _this, args;
    var previous = 0;

    return function() {
        var now = +new Date();
        _this = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(_this, args);
            previous = now;
        }
    }
}
复制代码

设置一个默认时间戳值为0, 当触发节流函数的时候,获取一个当前时间的时间戳,并减去前一个时间戳(默认时间),如果大于设置的等待时间,则立即执行函数, 并重置默认时间戳。

这样就达到了每隔一段时间就执行一次的效果了。

该方法会在触发后立即执行一次,停止触发则不只执行最近一次

定时器版

function throttle(func, wait) {
    var timeout;
    var previous = 0;

    return function() {
        _this = this;
        args = arguments;
        if (!timeout) {
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(_this, args)
            }, wait)
        }
    }
}
复制代码

触发事件时,判断定时器是否存在,如果存在的话就不执行,直到定时器自己执行,并清空自己。

否则的话,就设置一个延时定时器,等待函数执行。

并不会立即执行,但停止触发也会执行最近一次的调用

结合:有头有尾

function throttle(func, wait) {
    var timeout, _this, args, result;
    var previous = 0;

    var later = function() {
        previous = +new Date();
        timeout = null;
        func.apply(_this, args)
    };

    var throttled = function() {
        var now = +new Date();
        //下次触发 func 剩余的时间
        var remaining = wait - (now - previous);
        _this = this;
        args = arguments;
         // 如果没有剩余的时间或者修改了系统时间
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            func.apply(_this, args);
        } else if (!timeout) {
            timeout = setTimeout(later, remaining);
        }
    };
    return throttled;
}
复制代码

结合了前两种方法,在调用时,直接执行一次,停止触发也会执行最后一次。

算是有头有尾了。

总结

录制GIF的软件的死活装不上去,所以没法录制效果图了,需要用到的小伙伴可以自己建个html,写个demo测试下。

这里给个demo的模板

<body>
  <div id="wrap" style="width: 100px; height: 100px;"></div>
</body>
<script>
  let wrap = document.getElementById('wrap'),
      count = 1;
  function fn(){ console.log(1); }
  
  // throttle
  
  wrap.onmousemove = throttle(fn, 1000);
</script>
复制代码
文章分类
前端
文章标签