手写防抖、节流

106 阅读2分钟

介绍

防抖和节流本质上是优化了高频率的执行代码带来的性能损耗的一种技术手段!

例如,优化用户对设备进行高频率的交互操作。鼠标频繁点击、滚动、用户频繁的输入。这些频繁的动作会不断的调用事件处理函数,极大地浪费资源,降低前端页面性能!通过防抖和节流可以来很好的限制这些高频操作。

节流

节流:触发的事件处理函数在n秒内只运行一次,若在此期间内再次触发函数不再生效!

每次调用函数的时候获取当前,计算等待时间。若等待时间小于等于0则代表无需等待立即执行,并将开始时间设置为当前时间。若等待时间大于0则说明还没到执行时间,这时需要添加一个计时器setTimeout并设置延迟时间为等待时间。

function throttle(fn, delay) {
  let timeID = null; // 记录定时器ID
  let startTime = Date.now(); // 先设置开始时间
  return function () {
    let curTime = Date.now(); // 每次调用时获取一遍当前时间
    let awaitTime = delay - (curTime - startTime); // 等待时间

    if (timeID) clearTimeout(timeID); // 清除定时器
    if (awaitTime <= 0) {
      // 事件处理函数中,this 默认指向注册事件监听器的元素
      fn.apply(this, arguments); // 将函数的this绑定到到监听的元素上面,这样可以确保在fn中使用this操作元素
      startTime = Date.now(); // 重置开始时间
    } else {
      // 返回值 timeoutID 是一个正整数,表示由 setTimeout() 调用创建的定时器的编号。
      // 这个值可以传递给 clearTimeout() 来取消该定时器。
      timeID = setTimeout(fn, awaitTime);
    }
  };
}

防抖

防抖:n秒后执行触发的的事件处理函数,若在此期间再次触发,则重新计时。

function debounce(fn, wait) {
  let timeID;

  return function () {
      // 若在此期间再次触发,则清空计时器重新计时。
      if(timeID) clearTimeout(timeID)
      // 在wait秒后触发
      timeID = setTimeout(function() {
          fn.apply(this, arguments)
      }, wait);
  }
}