手撕面试常客之函数的防抖和节流

72 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

手撕面试常客之函数的防抖和节流

函数防抖

(debounce)在用户频繁触发某个行为的时候,我们只识别一次即可。

    /*
      debounce:函数防抖
      @params 
        func:自己最终要执行的任务
        wait:多久操作一次算是频繁触发[默认值:500ms]
        immediate:控制触发的边界[默认值:false结束边界  true开始边界](以点击按钮为例:[开始边界:第一次点击触发 结束边界:等到最后一次触发])
      @return
        operate处理函数,处理函数会在频繁触发的时候,频繁执行,函数内部,控制我们想要操作的func只执行一次
    */
    const debounce = function debounce(func, wait, immediate) {
      if (typeof func !== 'function')  throw new TypeError(`${func} is not a function`)
      if(typeof wait === 'boolean') immediate = wait
      if(typeof wait !== ' number') wait = 500
      if(typeof immediate !== 'boolean') immediate = false

      const clearTimer = function clearTimer(timer){
        if (timer) {
          clearTimeout(timer)
        }
        return null
      }

      let timer = null
      return function operate(...params){
        let now = !timer && immediate
        timer = clearTimer(timer)
        timer = setTimeout(() => {
          timer = clearTimer(timer)
          //结束边界触发
          if(!immediate) func.call(this, ...params)
        }, wait)
        //开始边界触发
        if (now) func.call(this, ...params)
      }
    }

函数节流

(throttle)在频繁操作的时候,我们能降低触发的频率 (执行的频率自己来设定)。

    /**
     * 
     * @param {*} func 需要处理的函数
     * @param {*} wait 多久触发一次
     *
     * @return
            operate处理函数,处理函数会在频繁触发的时候,频繁执行,函数内部,控制我们想要操作的func按照规定的频率执行
     */
    const throttle = function throttle(func, wait){
      if(typeof func !== 'function') throw new TypeError(`${func} is not a function`)
      if(typeof wait !== 'number') wait = 500

      const clearTimer = function clearTimer(tiemr){
        if (timer) {
          clearTimeout(timer)
        }
        return null
      }

      let timer = null,
          previous = 0
      return function operate(...params){
        let now = +new Date(),
            remaining = wait - (now - previous)
        if (remaining <= 0) {
          // 两次间隔时间超过500ms了,让其方法立即执行
          func.call(this, ...params)
          previous = +new Date()
        }else if (!timer) {
          // 没设置过定时器等待,则我们设置一个去等待
          timer = setTimeout(() => {
            timer = clearTimer(timer)
            func.call(this, ...params)
            previous = +new Date()
          }, remaining)
        }
      }
    }