JavaScript技巧: 节流、防抖

183 阅读2分钟

防抖和节流都是为了解决短时间内大量触发某函数而导致的性能问题,比如触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象

节流

在 wait 时间内,callback 只能执行一次(在指定时间内执行一次)

/**
 * * 1、事件函数 节流(在 wait 时间内,callback 只能执行一次) 实现
 * ? 此函数利用时间戳,判断事件触发的时间间隔,如果触发时间间隔少于设置的时间间隔,则不允许事件触发;以减少频繁触发事件的触发频率,提升系统效率
 * ! 注意:返回的函数中通过 call 函数指定调用者, 如不指定,则由 window 全局变量调用此函数
 *
 * @param {Function} callback 回调函数
 * @param {Number} wait 允许调用的时间间隔
 * @return {Function} 函数对象,包括函数调用并将间隔判断值作更新
 */
function throttle(callback, wait) {
  // 间隔判断值
  let start = 0
  // 返回值为一个函数
  return function (e) {
    // 函数执行时时间
    let now = Date.now()
    // 触发时间判断
    if (now - start >= wait) 
      callback.call(this, e)
      start = now
    }
  }
}

docement.qs('#app').scroll = throttle(function(e){
  console.log(e)
},500)

防抖

在一次函数调用后,延迟 time 毫秒后调用 callback ,重置触发则重置延迟毫秒数(在满足规定时间要求后执行一次)

/**
 * * 2、事件函数 防抖(在一次函数调用后,延迟 time 毫秒后调用 callback ,重置触发则重置延迟毫秒数) 实现
 * ? 此函数利用定时器,判断事件触发的时间间隔,如果触发时间间隔在延迟毫秒事件内重置触发,则重置事件触发定时器;以减少规定时间内,触发事件的触发频率,提升系统效率
 * ! 注意:返回的定时器函数中通过 call 函数指定调用者, 如不指定,则由 window 全局变量调用此函数
 *
 * @param {Function} callback 回调函数
 * @param {Number} time 允许调用的时间间隔
 * @return {Function} 函数对象,包括函数调用并将间隔判断值作更新
 */
function debounce(callback, time) {
  // 设置触发判断值
  let timeId = null
  // 返回值为一个函数
  return function (e) {
    // timeId只要改变,在执行至此时关闭上一个定时器,重置定时器,实现防抖
    if (timeId !== null) {
      clearTimeout(timeId)
    }

    timeId = setTimeout(() => {
      // 执行回调函数
      callback.call(this, e)
      // 执行成功重置触发判断值,如果执行成功后不重置触发判断值,则没触发情况下 if !== null 判断无用
      timeId = null
    }, time)
  }
}