debounce(防抖)和throttle(节流)

本文介绍了JavaScript中防抖(debounce)与节流(throttle)技术的实现原理及应用场景,帮助开发者有效降低事件处理频率,提升用户体验。

debounce(防抖)和throttle(节流)

在处理诸如 resize、scroll、mousemove、keydown / keyup / keypress 等事件和输入框内容校验等操作的时候,通常我们不希望这些事件太过频繁地触发,尤其是监听程序中涉及到大量的计算或者有非常耗费资源的操作。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少触发的频率,同时又不影响实际效果。

debounce 防抖

在 JavaScript 中,debounce 函数所做的事情就是,在用户停止某个操作一段时间之后才执行相应的监听函数,而不是在用户操作的过程当中,浏览器触发多少次事件,就执行多少次监听函数。

从上图中我们可以看到,当持续触发事件时,debounce会合并事件且不会去触发事件,当一定时间内没有触发再这个事件时,才真正去触发事件。

/**
*
* @param fn {Function}   实际要执行的函数
* @param delay {Number}  延迟时间,也就是阈值,单位是毫秒(ms)
*
* @return {Function}     返回一个防抖的函数
*/

function debounce(fn, delay) {
  var ctx;
  var args;
  var timer = null;

  var later = function () {
    fn.apply(ctx, args);
    // 当事件真正执行后,清空定时器
    timer = null;
  };

  return function () {
    ctx = this;
    args = arguments;
    // 当持续触发事件时,若发现事件触发的定时器已设置时,则清除之前的定时器
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    // 重新设置事件触发的定时器
    timer = setTimeout(later, delay);
  };
}

throttle 节流

当持续触发事件时,保证隔间时间触发一次事件。

上图中绿色块表示触发一次事件,持续触发事件时,throttle会合并一定时间内的事件,并在该时间结束时真正去触发一次事件。

/**
*
* @param fn {Function}   实际要执行的函数
* @param delay {Number}  执行间隔,单位是毫秒(ms)
*
* @return {Function}     返回一个“节流”函数
*/

function throttle(fn, delay) {
  var ctx;
  var args;
  // 记录上次触发事件
  var previous = Date.now();

  var later = function () {
    fn.apply(ctx, args);
  };

  return function () {
    ctx = this;
    args = arguments;
    var now = Date.now();
    // 本次事件触发与上一次的时间比较
    var diff = now - previous - delay;

    // 如果隔间时间超过设定时间,即再次设置事件触发的定时器
    if (diff >= 0) {
      // 更新最近事件触发的时间
      previous = now;
      setTimeout(later, delay);
    }
  };
}
### 防抖Debounce防抖是指如果一个函数持续地触发,那么只在它结束后过一段时间只执行一次,常用于搜索查询等场景,避免在事件持续触发过程中频繁请求接口 [^1]。 #### 实现函数 ```javascript function debounce(func, delay) { let timer = null; return function(...args) { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { func.apply(this, args); timer = null; }, delay); }; } ``` #### 使用方法 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <input type="text" id="searchInput"> <script> function search(query) { console.log(`搜索: ${query}`); } const debouncedSearch = debounce(search, 300); const input = document.getElementById('searchInput'); input.addEventListener('input', function() { debouncedSearch(input.value); }); </script> </body> </html> ``` ### 节流Throttle节流是指在一定时间内只允许函数执行一次,无论触发多少次事件,函数都只在规定的时间间隔内执行一次,常用于滚动事件、提交保存等场景 [^2]。 #### 实现函数 ```javascript function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } ``` #### 使用方法 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <button id="submitButton">提交</button> <script> function submitForm() { console.log('表单提交'); } const throttledSubmit = throttle(submitForm, 1000); const button = document.getElementById('submitButton'); button.addEventListener('click', throttledSubmit); </script> </body> </html> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值