手写节流与防抖

防抖:时间响应函数在一段时间之后才执行,如果在这段时间内再次调用,则会重新计算时间,当预定的时间内没有再次调用该函数,则执行响应逻辑。

  function debounce(func, wait, immediate = true) {
    // 定义一个timeout计时器
    let timeout, result;
    let debounced = function () {
      // 如果每次进入函数的时候timeout有值,说明等待时间还没有过,不执行函数,清空timeout
      // 如果没有timeout,则说明过了等待期,可以执行函数
      if (timeout) clearTimeout(timeout);
      // 默认立即执行方法,延后执行的话,会让人感觉有卡顿
      if (immediate) {
        let now = !timeout;
        if (now) result = func.apply(this, arguments);
        // 不论timeout有没有值,都重新给timeout新添加一个定时器
        // 等待wait时间后,将timeout设为null,代表可以继续执行此次function
        timeout = setTimeout(() => {
          timeout = null;
        }, wait);
      } else {
        // 如果不是立即执行此函数,则在等待wait时间后执行方法
        timeout = setTimeout(() => {
          func.apply(this, arguments);
        }, wait);
      }
      // 函数返回的内容
      return result;
    }

    // 取消防抖操作
    debounced.cancel = function () {
      clearTimeout(timeout);
      timeout = null;
    }

    return debounced;
  }

应用场景:

1、scroll滚动

2、浏览器窗口resize事件

3、搜索框查询

4、按钮提交事件

节流:如果持续触发事件,则每隔一段时间,只执行一次操作

使用时间戳完成节流函数

   // 第一次会触发,最后一次不会触发
  function throttle1(func, wait) {
    let old = 0;
    return function () {
      let now = +new Date();
      if (now - old > wait) {
        old = now;
        func.apply(this, arguments);
      }
    }
  }

使用定时器完成节流函数

   // 第一次不会触发,最后一次会触发
  function throttle2(func, wait) {
    let timeout;
    return function () {
      if (!timeout) {
        timeout = setTimeout(() => {
          func.apply(this, arguments);
          timeout = null;
        }, wait)
      }
    }
  }

时间戳和定时器结合完成节流函数

该函数接收第三个参数options:

第一次会触发,最后一次不会触发  leading: true, trailing: false
第一次不会触发,最后一次会触发  leading: false, trailing: true
第一次会触发,最后一次也会触发  leading: true, trailing: true
   // 第一次会执行,最后一次也会执行 
 function throttle(func, wait, options = {}) {
    let timeout, old = 0;

    const { leading = true, trailing = true } = options;
    return function () {
      let now = +new Date();

      // 第一次会执行
      if (now - old > wait && leading) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        old = now;
        func.apply(this, arguments);
      }
      // 最后一次会执行
      if (!timeout && trailing) {
        timeout = setTimeout(() => {
          old = +new Date();
          func.apply(this, arguments);
          timeout = null;
        }, wait)
      }
    }
  }

应用场景:

1、DOM元素的拖拽

2、射击游戏

3、计算鼠标移动的距离

4、监听scroll滚动事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值