2019-06-03 节流函数-复习

节流:

应用场景:监听滚动事件,比如是否滑到底部自动加  、重复点击按钮提交事件

节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。
举例说明:小明的妈妈和小明约定好,如果小明在周考中取得满分,那么当月可以带他去游乐场玩,但是一个月最多只能去一次。
这其实就是一个节流的例子,在一个月的时间内,去游乐场最多只能触发一次。即使这个时间周期内,小明取得多次满分

节流函数实现方式

1、利用时间戳实现

function throttle (func, delay) {
    var lastTime = 0;
    function throttled() {
        var context = this;
        var args = arguments;
        var nowTime = Date.now();
        if(nowTime > lastTime + delay) {
            func.apply(context, args);
            lastTime = nowTime;
        }
    }
    //节流函数最终返回的是一个函数
    return throttled; 
}

2、定时器实现

function throttle(func, delay) {
    var timeout = null;
    function throttled() {
        var context = this;
        var args = arguments;
        if(!timeout) {
            timeout = setTimeout(()=>{
                func.apply(context, args);
                clearTimeout(timeout);
                timeout=null
            }, delay);
        }
    }
    return throttled;
}

注释:

时间戳和定时器的方式都没有考虑最后一次执行的问题,比如有个按钮点击事件,设置的间隔时间是1S,在第0.5S,1.8S,2.2S点击,那么只有0.5S和1.8S的两次点击能够触发函数执行,而最后一次的2.2S会被忽略。

3、组合实现,允许设置第一次或者最后一次是否触发函数执行

function throttle (func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function () {
        previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };

    var throttled = function () {
        var now = Date.now() || new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            // 判断是否设置了定时器和 trailing
            timeout = setTimeout(later, remaining);
        }
        return result;
    };

    throttled.cancel = function () {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };

    return throttled;
}

实现方式

btn.onclick = throttle(handle, 1000, {leading:true, trailing: true});

防抖:(debounce)

触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

实现思路:

每次触发事件时都取消之前的延时调用方法
function debounce(fn) {
      let timeout = null; // 创建一个标记用来存放定时器的返回值
      return function () {
        clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(this, arguments);
        }, 500);
      };
    }
    function sayHi() {
      console.log('防抖成功');
    }

    var inp = document.getElementById('inp');
    inp.addEventListener('input', debounce(sayHi)); // 防抖
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本篇课题,或许早已是烂大街的解读文章。不过春招系列面试下来,不少伙伴们还是似懂非懂地栽倒在(~面试官~)深意的笑容...
    以乐之名阅读 1,801评论 0 9
  • 函数节流 还记得上篇文章中说到的图片懒加载吗?我们在文章的最后实现了一个页面滚动时按需加载图片的方式,即在触发滚动...
    柏丘君阅读 2,870评论 1 19
  • 前言 最近和前端的小伙伴们,在讨论面试题的时候。谈到了函数防抖和函数节流的应用场景和原理。于是,想深入研究一下两者...
    youthcity阅读 23,626评论 5 78
  • 1.清除盒模型的浮动方式 way 1: 最后追加元素, 设置 clear:both; way 2: 伪元素清除 d...
    Hyb_7818阅读 655评论 0 0
  • 标签:debounce throttle iplas 小编在偶然浏览Javascript技术贴吧时候,偶然看到节...
    傑仔阅读 537评论 0 2