个人的博客
个人的博客

防抖/节流

防抖(Debounce)和节流(throttle)都是用来控制某个函数在一定时间内执行多少次的技巧,两者相似而又不同。

# 防抖/节流

防抖(Debounce)和节流(throttle)都是用来控制某个函数在一定时间内执行多少次的技巧,两者相似而又不同。

# 防抖(debounce)

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
及短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。

以下为执行最后一次触发,且非立即执行版:

/**
 * @desc 非立即执行版
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 */
function debounce(func,wait){
  let timer
  return function(){
    let _this = this
    let args = arguments

    if(timer) clearTimeout(timer)

    timer = setTimeout(()=>{
      func.apply(_this,args)
    },wait)
  }
}

以下为执行最开始的一次触发,且立即执行版:

/**
 * @desc 立即执行版
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 */
function debounce(func,wait){
  let timer
  return function(){
    let _this = this
    let args = arguments

    if(timer) clearTimeout(timer)

    let flag = !timer
    timer = setTimeout(()=>{
      timer = null
    },wait)

    if(flag) func.apply(_this,args)
  }
}

最后合并为以下版本:

/**
 * @desc 函数防抖
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 * @param immediate 是否立即执行,true 表立即执行,false 表非立即执行
 */
function debounce(func, wait = 300, immediate = true) {
  let timer;
  const _debounce = function () {
    let args = arguments;
    let context = this
    if (timer) clearTimeout(timer)

    if (immediate ) {
      let flag = !timer
      timer = setTimeout(()=>{
        timer = null
      }, wait)
      if(flag) func.apply(context, args)
    } else {
      timer = setTimeout(() => {
        func.apply(context, args)
      }, wait)
    }
  }
  _debounce.cancel = function () {
    clearTimeout(timer)
    timer = null
  }
  return _debounce
}

# 节流(throttle)

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。即2n秒内执行2次...... 。如字面意思,节流作用是稀释函数的的执行频率。 函数节流 时间戳版(函数会立即执行)

/**
 * 函数节流 时间戳版(函数会立即执行)
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 */
function throttleByTimestamp(func, wait = 300) {
  let previous = 0
  const _throttle = function () {
    let args = arguments
    let context = this
    let now = Date.now()
    if (now - previous > wait) {
      func.apply(context, args)
      previous = now
    }
  }
  return _throttle
}

函数节流 定时器版(函数不会立即执行)

/**
 * 函数节流 定时器版(函数不会立即执行)
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 */
function throttleByTimer(func, wait = 300) {
  let timer = 0
  const _throttle = function () {
    let args = arguments
    let context = this
    if (!timer) {
      timer = setTimeout(() => {
        timer = null
        func.apply(context, args)
      }, wait)
    }
  }
  return _throttle
}

函数节流 整合版

/**
 * @desc 函数节流 整合版
 * @param func 函数 
 * @param wait 延迟执行毫秒数
 * @param immediate 是否立即执行,true 表立即执行,false 表非立即执行
 */
function throttle(func, wait = 300, immediate = true) {
  let previous = new Date(0).getTime()
  let timer
  const _throttle = function () {
    let args = arguments
    let context = this
    if (immediate) {
      let now = new Date().getTime()
      if (now - previous > wait) {
        func.apply(context, args)
        previous = now
      }
    } else {
      if (!timer) {
        timer = setTimeout(() => {
          timer = null
          func.apply(context, args)
        }, wait)
      }
    }
  }
  _throttle.cancel = () => {
    previous = 0
    clearTimeout(timer)
    timer = null
  }
  return _throttle
}