欢迎光临
我们一直在努力

如何手写防抖节流?一文教你掌握JavaScript中的这一技巧!

一文学会JavaScript如何手写防抖节流

如何手写防抖节流?一文教你掌握JavaScript中的这一技巧!

一、什么是防抖和节流

1、防抖(Debounce)

定义:在事件触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

应用场景:输入框实时搜索、窗口调整等。

实现思路:通过定时器实现,如果在规定时间内再次触发事件,则清除上一次的定时器并重新设置。

2、节流(Throttle)

定义:对于连续多次触发的事件,每隔一段固定时间执行一次。

如何手写防抖节流?一文教你掌握JavaScript中的这一技巧!

应用场景:鼠标点击、监听滚动事件、input输入等。

实现思路:通过记录上次执行的时间戳,判断当前时间与上次时间的差值是否大于设定的间隔时间,如果是则执行函数。

二、防抖的实现

基本版

function debounce(fn, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(fn, delay);
  }
}

闭包优化版

function debounce(fn, delay) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  }
}

立即执行增强版

function debounce(fn, delay) {
  let timer;
  let isImmediatelyInvoked = false;
  return function() {
    const context = this;
    const args = arguments;
    if (!isImmediatelyInvoked) {
      fn.apply(context, args);
      isImmediatelyInvoked = true;
    }
    clearTimeout(timer);
    timer = setTimeout(function() {
      isImmediatelyInvoked = false;
    }, delay);
  }
}

三、节流的实现

时间戳版

function throttle(fn, wait) {
  let preTime = 0;
  return function() {
    const context = this;
    const args = arguments;
    const now = +new Date();
    if (now  preTime > wait) {
      fn.apply(context, args);
      preTime = now;
    }
  }
}

定时器版

function throttle(fn, wait) {
  let timeout;
  return function() {
    const context = this;
    const args = arguments;
    if (!timeout) {
      timeout = setTimeout(function() {
        fn.apply(context, args);
        timeout = null;
      }, wait);
    }
  }
}

组合版

function throttle(fn, wait) {
  let preTime = 0;
  let timeout;
  return function() {
    const context = this;
    const args = arguments;
    const now = +new Date();
    const remaining = wait  (now  preTime);
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      preTime = now;
      fn.apply(context, args);
    } else if (!timeout) {
      timeout = setTimeout(function() {
        preTime = +new Date();
        timeout = null;
        fn.apply(context, args);
      }, remaining);
    }
  }
}

四、自定义版节流

在组合版的基础上,设置一个options对象参数,根据传的值判断要哪一种效果,规定:

leading: false表示禁用第一次执行。

如何手写防抖节流?一文教你掌握JavaScript中的这一技巧!

trailing: false表示禁用停止触发的回调。

function throttle(fn, wait, options = {}) {
  let timeout;
  let preTime = 0;
  const leading = options.leading === false;
  const trailing = "trailing" in options ? options.trailing : true;
  return function() {
    const context = this;
    const args = arguments;
    const now = +new Date();
    if (!leading && now < preTime) return; // 禁用第一次执行
    const remaining = wait  (now  preTime);
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      preTime = now;
      fn.apply(context, args);
      if (!trailing) return; // 禁用停止触发的回调
    } else if (!timeout) {
      timeout = setTimeout(function() {
        preTime = +new Date();
        timeout = null;
        fn.apply(context, args);
      }, remaining);
    }
  }
}

五、相关问题与解答栏目

1. 什么时候使用防抖和节流?它们有什么区别?

解答:防抖和节流都是用于限制高频事件触发的性能优化手段,防抖是将多次事件触发合并为最后一次触发,适用于输入框搜索、窗口调整等场景;而节流是每隔一段时间只执行一次事件,适用于滚动事件、鼠标移动等场景,具体选择哪种方式取决于实际需求。

如何在项目中应用防抖和节流?

解答:可以通过将防抖或节流函数封装后绑定到相应的事件上来实现,对于输入框的实时搜索功能,可以使用防抖函数来减少搜索请求的次数;对于滚动加载更多数据的功能,可以使用节流函数来控制数据加载的频率,具体实现可以参考上述代码示例。

各位小伙伴们,我刚刚为大家分享了有关“一文学会JavaScript如何手写防抖节流”的知识,希望对你们有所帮助。如果您还有其他相关问题需要解决,欢迎随时提出哦!

赞(0)
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《如何手写防抖节流?一文教你掌握JavaScript中的这一技巧!》
文章链接:https://yuyunkj.com/article/10373.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发