JavaScript 中的防抖和节流

韩小韩
2021-08-28 / 0 评论 / 296 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年08月28日,已超过943天没有更新,若内容或图片失效,请留言反馈。

什么是防抖

函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。如下图,持续触发 scroll 事件时,并不执行 handle 函数,当 1000 毫秒内没有触发 scroll 事件时,才会延时触发 scroll 事件。

JavaScript 中的防抖和节流

防抖应用场景如下

  • 搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。
  • 表单验证
  • 按钮提交事件。
  • 浏览器窗口缩放,resize 事件 (如窗口停止改变大小之后重新计算布局) 等。

具体实现

非立即执行版

function debounce(func, wait) {
  let timeout;
  return function () {
    let context = this;
    let args = arguments;
    if (timeout) clearTimeout(timeout);      
    timeout = setTimeout(() => {
      func.apply(context, args)
    }, wait);
  }
}

立即执行版

function debounce(func,wait) {
  let timeout;
  return function () {
    let context = this;
    let args = arguments;
    if (timeout) clearTimeout(timeout);
    let callNow = !timeout;
    timeout = setTimeout(() => {
      timeout = null;
    }, wait)
    if (callNow) func.apply(context, args)
  }
}

什么是节流

函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。如下图,持续触发 scroll 事件时,并不立即执行 handle 函数,每隔 1000 毫秒才会执行一次 handle 函数。

JavaScript 中的防抖和节流

节流应用场景

  • 按钮点击事件
  • 拖拽事件
  • onScoll
  • 计算鼠标移动的距离 (mousemove)

具体实现

时间戳版

function throttle(func, wait) {
  let previous = 0;
  return function() {
    let now = Date.now();
    let context = this;
    let args = arguments;
    if (now - previous > wait) {
      func.apply(context, args);
      previous = now;
    }
  }
}

定时器版

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

定时器 + 时间戳版本

// 节流throttle代码(时间戳+定时器):
var throttle = function(func, delay) {     
  var timer = null;     
  var startTime = Date.now();     
  return function() {             
    var curTime = Date.now();             
    var remaining = delay - (curTime - startTime);             
    var context = this;             
    var args = arguments;             
    clearTimeout(timer);              
    if (remaining <= 0) {                    
      func.apply(context, args);                    
      startTime = Date.now();              
    } else {                    
      timer = setTimeout(func, remaining);              
    }      
  }
}

总结

函数防抖

函数节流

区别

2

评论 (0)

取消