【进阶 6-6 期】深入篇 | 阿里 P6 必会 Lodash 防抖节流函数实现原理

引言

前面几节我们学习了节流函数 throttle,防抖函数 debounce,以及各自如何在 React 项目中进行应用,今天这篇文章主要聊聊 Lodash 中防抖和节流函数是如何实现的,并对源码浅析一二。下篇文章会举几个小例子为切入点,换种方式继续解读源码,敬请期待。

有什么想法或者意见都可以在评论区留言,欢迎大家拍砖。

防抖函数 debounce

Lodash 中节流函数比较简单,直接调用防抖函数,传入一些配置就摇身一变成了节流函数,所以我们先来看看其中防抖函数是如何实现的,弄懂了防抖,那节流自然就容易理解了。

防抖函数的定义和自定义实现我就不再介绍了,之前专门写过一篇文章,戳这里学习

进入正文,我们看下 debounce 源码,源码不多,总共 100 多行,为了方便理解就先列出代码结构,然后再从入口函数着手一个一个的介绍。

代码结构

function debounce(func, wait, options) {
   
  // 通过闭包保存一些变量
  let lastArgs, // 上一次执行 debounced 的 arguments,
      					// 起一个标记位的作用,用于 trailingEdge 方法中,invokeFunc 后清空
    lastThis, // 保存上一次 this
    maxWait, // 最大等待时间,数据来源于 options,实现节流效果,保证大于一定时间后一定能执行
    result, // 函数 func 执行后的返回值,多次触发但未满足执行 func 条件时,返回 result
    timerId, // setTimeout 生成的定时器句柄
    lastCallTime // 上一次调用 debounce 的时间

  let lastInvokeTime = 0 // 上一次执行 func 的时间,配合 maxWait 多用于节流相关
  let leading = false // 是否响应事件刚开始的那次回调,即第一次触发,false 时忽略
  let maxing = false // 是否有最大等待时间,配合 maxWait 多用于节流相关
  let trailing = true // 是否响应事件结束后的那次回调,即最后一次触发,false 时忽略

  // 没传 wait 时调用 window.requestAnimationFrame()
  // window.requestAnimationFrame() 告诉浏览器希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画,差不多 16ms 执行一次
  const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function')

  // 保证输入的 func 是函数,否则报错
  if (typeof func !== 'function') {
   
    throw new TypeError('Expected a function')
  }
  
  // 转成 Number 类型
  wait = +wait || 0
  
  // 获取用户传入的配置 options
  if (isObject(options)) {
   
    leading = !!options.leading
    // options 中是否有 maxWait 属性,节流函数预留
    maxing = 'maxWait' in options
    // maxWait 为设置的 maxWait 和 wait 中最大的,如果 maxWait 小于 wait,那 maxWait 就没有意义了
    maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait
    trailing = 'trailing' in options ? !!options.trailing : trailing
  }
  
  // ----------- 开闭定时器 -----------
  // 开启定时器
  function startTimer(pendingFunc, wait) {
   }

  // 取消定时器
  function cancelTimer(id) {
   }

  // 定时器回调函数,表示定时结束后的操作
  function timerExpired() {
   }
  
  // 计算仍需等待的时间
  function remainingWait(time) {
   }
  
  // ----------- 执行传入函数 -----------
	// 执行连续事件刚开始的那次回调
  function leadingEdge(time) {
   }
  
  // 执行连续事件结束后的那次回调
  function trailingEdge(time) {
   
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值