just-debounce函数学习

33 阅读4分钟

距离上次学习clone函数已经好几周了,由于我现在的理念是尽可能的能坚持长期学习,所以我给自己的任务没有很重,会更倾向于轻松一点,但是可能前两周有点太宽松了,就没有花时间在学习上。这两天又慢慢的把自己的状态调整回来,然后我又回到了debounce函数。

这个函数我目前已经看了很多遍了,我感觉基本上每一行我都能理解它的用意,我觉得这个过程是有趣的。

在分析的过程中,我学到了一个方法,那就是脑子里有一个作用域,你要记得代码跑到某个地方的时候,你有哪些变量可以用,因为除了关键字,能出现的就是这些变量,我觉得这样会有一个大局观吧,就是你会记得这个变量,记得它是在哪里声明的,它用了几次(它的用处)。还有一个好处就是,在代码正常执行完毕后,如果你知道此时还有哪些变量,那么你也能更好的去重置变量的状态,使你不那么容易忽略它。

虽然只是一个小小的debounce函数,我觉得在我工作了几年之后,读了这样的代码之后我还是会有很多收获,有可能是自己基础太差了,也有可能工作上追求的是效率,自己根本没有花时间在编码上,心态上会比较随意,然后出现问题了就一顿乱改,到最后能运行就行。不过工作确实比较特殊,可能真的没那么多时间让我来思考这些,所以更多的还是需要自主驱动,通过阅读一些好的代码,熟悉一些好的写法,把它带到工作当中,这样会更好。

下面的代码是我读了just的源码后自己写的,不过我觉得我也只是记住了这种写法,或许还没有真正的理解 因为在阅读了别人的代码之后,你写出来的代码多多少少会带点别人的影子,不过我觉得应该许多人都要经历这种过程吧,当你肚子里没有墨水的时候,你只能先模仿别人的东西,慢慢理解变成自己的东西,等你掌握的足够多之后,才能输出真正属于自己的东西。

接下来我描述一下我在写这个函数时的心理活动吧

首先我觉得写好一个函数,我需要知道这个函数的功能

比如这是一个防抖函数,要有正常的防抖功能,通过外部取消定时器,通过外部立马执行

然后我会思考它的参数和返回值

比如接收一个函数,延时时间,是否需要首次执行。
返回值则是一个函数

内部细节及其它

其他的内部细节我觉得我还讲不出来,功力应该还不够,我还没有真正的理解它,我只是能够模仿它

function debounce(fn, wait, callFirst) {
  let timeout = null
  let debouncedFn = null

  // flush需要调用
  // 1.清除定时器
  // 2.直接调用debounce函数,并且需要重置该函数
  // 

  // 重新开始定时任务前需要调用
  // 1.清除定时器, timeout重置为null
  // 2.debounce函数重置为null

  // 外部取消定时器时需要调用
  // 和flush大致相同

  const clear = function () {
    if (timeout) {
      clearTimeout(timeout)

      timeout = null
      debouncedFn = null
    }
  }

  // 获取防抖函数
  // 调用clar
  // 执行防抖函数
  const flush = function () {
    const fn = debouncedFn
    clear()

    if (fn) {
      fn()
    }
  }

  const wrapper = function (...args) {
    // 直接调用
    // wait为各种False值时
    if (!wait) {
      return fn.apply(this, args)
    }

    // 定时调用
    // 分为两种情况
    // 是否需要立马调用一次
    const callNow = !timeout && callFirst
    const context = this
    clear()

    debouncedFn = function () {
      return fn.apply(context, args)
    }
    
    timeout = setTimeout(() => {
      timeout = null

      if (!callNow) {
        const call = debouncedFn
        debouncedFn = null

        return call()
      }
    }, wait);

    if (callNow) {
      return debouncedFn()
    }

  }

  wrapper.cancel = clear
  wrapper.flush = flush

  return wrapper
}

下一个函数我会去学习just中的pick函数,也就是从对象中取出对应的key变成一个新对象