JavaScript函数防抖节流

开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们不希望频繁地去执行函数,因为这样会导致一些性能问题,比如发送大量Ajax请求或者大量执行js代码导致页面卡顿 渲染阻塞

防抖是控制次数(加技能前摇),节流是控制频率(加技能cd)

防抖 (debounce)

效果:如果短时间内大量触发同一事件,只会执行一次函数

//  防抖 (debounce)
/**
 * @desc 函数防抖
 * @param func 函数
 * @param delay 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
function debounce(func,delay,immediate) {
  let timeout;

  return function () {
    let context = this;
    let args = arguments;

    if (timeout) clearTimeout(timeout);
    if (immediate) {
      let callNow = !timeout;
      timeout = setTimeout(() => {
        timeout = null;
      }, delay)
      if (callNow) func.apply(context, args)

    }else {
      timeout = setTimeout(function(){
        func.apply(context, args)
      }, delay);
    }
  }
}

export default debounce

节流(throttle)

节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效 (进入了技能cd)

对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。

定时器版本

/**
 * 函数节流
 * @param {function} func - 需要节流的函数
 * @param {number} delay - 执行延迟
 **/
function throttle(func, delay) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, delay)
        }

    }
}

时间戳版本

/**
 * 函数节流
 * @param {function} func - 需要节流的函数
 * @param {number} delay - 执行延迟
 **/
function throttle(func, delay) {
    let previous = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > delay) {
            func.apply(context, args);
            previous = now;
        }
    }
}
目录