Lodash源码阅读-baseWhile

Lodash 源码阅读-baseWhile

概述

baseWhile 是 Lodash 内部的一个工具函数,它是实现 _.takeWhile_.dropWhile_.takeRightWhile_.dropRightWhile 等方法的基础。这个函数负责根据指定条件从数组中提取或排除元素,支持从数组开头或结尾开始处理。

前置学习

依赖函数

  • baseSlice:数组切片的底层实现函数
  • getIteratee:获取迭代器函数的工具

技术知识

  • 数组操作:理解数组索引和切片操作
  • 谓词函数:接受值并返回布尔值的函数
  • 循环控制:使用条件控制循环的执行方式
  • 高阶函数:接受或返回函数的函数设计模式
  • 函数组合:将多个函数组合在一起形成新功能

源码实现

javascript 复制代码
function baseWhile(array, predicate, isDrop, fromRight) {
  var length = array.length,
    index = fromRight ? length : -1;

  while (
    (fromRight ? index-- : ++index < length) &&
    predicate(array[index], index, array)
  ) {}

  return isDrop
    ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length)
    : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
}

实现思路

baseWhile 函数的实现思路巧妙而高效,它通过四个核心步骤完成工作:

  1. 初始化必要的变量,包括数组长度和起始索引位置
  2. 根据 fromRight 参数决定从数组的开头还是末尾开始循环
  3. 使用 while 循环,对数组元素应用谓词函数,直到找到第一个不满足条件的元素
  4. 根据 isDropfromRight 参数,选择适当的数组切片方式返回结果

这种实现允许一个函数同时支持四种不同的操作模式(take、drop、从左、从右),大大减少了代码重复。

源码解析

参数初始化

javascript 复制代码
var length = array.length,
  index = fromRight ? length : -1;

这里初始化了两个关键变量:

  • length:数组的长度,用于控制循环边界
  • index:迭代的起始位置,根据 fromRight 决定是从数组末尾(length)开始,还是从开头前一个位置(-1)开始

循环处理

javascript 复制代码
while (
  (fromRight ? index-- : ++index < length) &&
  predicate(array[index], index, array)
) {}

这个循环包含两个关键部分:

  1. 索引更新与边界检查:(fromRight ? index-- : ++index < length)

    • 从右侧开始:递减 indexindex--
    • 从左侧开始:递增 index 并检查是否小于数组长度(++index < length
  2. 条件检查:predicate(array[index], index, array)

    • 对当前元素应用谓词函数
    • 传入三个参数:当前元素值、索引和原数组
    • 只要谓词返回真值,循环就会继续

这个循环会一直运行,直到遇到第一个不满足谓词条件的元素,或者遍历完整个数组。

结果处理

javascript 复制代码
return isDrop
  ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length)
  : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);

这部分代码根据 isDropfromRight 参数,调用 baseSlice 从数组中返回适当的切片:

  1. isDroptrue 时(丢弃模式):

    • 从右侧开始:保留索引 0 到 index 的元素
    • 从左侧开始:保留索引 index 到末尾的元素
  2. isDropfalse 时(保留模式):

    • 从右侧开始:保留索引 index+1 到末尾的元素
    • 从左侧开始:保留索引 0 到 index 的元素

这种设计让 baseWhile 能够灵活地处理四种不同的操作模式。

isDrop 参数不同取值的运行过程

我们通过具体例子来说明 isDrop 参数如何影响函数行为:

假设有数组 [1, 2, 3, 4, 5],谓词函数为 x => x < 3(即检查元素是否小于 3):

1. isDrop = false(保留满足条件的元素)

这对应于 takeWhiletakeRightWhile 函数:

  • 从左开始 (fromRight = false)

    • 循环从索引 0 开始,依次检查元素[1, 2],直到遇到元素 3(不满足条件)
    • 此时 index = 2
    • 返回 baseSlice(array, 0, 2)[1, 2]
    • 这就是 takeWhile 的行为:保留开头连续满足条件的元素
  • 从右开始 (fromRight = true)

    • 循环从末尾(索引 4)开始,因为没有元素满足条件(都大于等于 3)
    • 此时 index = 4(循环未进入)
    • 返回 baseSlice(array, 5, 5)[]
    • 如果数组是 [6, 5, 4, 2, 1],则会返回 [2, 1]
    • 这就是 takeRightWhile 的行为:保留末尾连续满足条件的元素
2. isDrop = true(丢弃满足条件的元素)

这对应于 dropWhiledropRightWhile 函数:

  • 从左开始 (fromRight = false)

    • 循环从索引 0 开始,依次检查元素[1, 2],直到遇到元素 3(不满足条件)
    • 此时 index = 2
    • 返回 baseSlice(array, 2, 5)[3, 4, 5]
    • 这就是 dropWhile 的行为:丢弃开头连续满足条件的元素
  • 从右开始 (fromRight = true)

    • 循环从末尾(索引 4)开始,因为没有元素满足条件(都大于等于 3)
    • 此时 index = 4(循环未进入)
    • 返回 baseSlice(array, 0, 5)[1, 2, 3, 4, 5](原数组)
    • 如果数组是 [6, 5, 4, 2, 1],则会返回 [6, 5, 4]
    • 这就是 dropRightWhile 的行为:丢弃末尾连续满足条件的元素

这种设计通过组合 isDropfromRight 参数,使得一个函数可以实现四种相关但不同的操作,展示了 Lodash 优秀的代码复用能力。注意循环的终止条件和切片范围的选择是这个函数的精髓所在。

总结

baseWhile 函数展示了 Lodash 优秀的代码设计原则:

  1. 代码复用:一个函数通过参数组合支持多种功能,减少重复代码
  2. 抽象分层:将核心逻辑抽象到内部函数,公共 API 只需简单包装
  3. 参数灵活性:通过布尔参数控制函数行为,实现多态
  4. 高效实现:通过精心设计的循环和条件判断,确保性能最优
相关推荐
天涯学馆几秒前
解锁大前端性能优化的终极秘籍,让你的页面飞起来!
前端·javascript·面试
萌萌哒草头将军40 分钟前
🚀🚀🚀 尤雨溪宣布 Vite 发布 Rolldown-Vite 预览版,性能超级快!⚡️⚡️⚡️
前端·vue.js·vite
simon_934941 分钟前
静态资源js,css免费CDN服务比较
开发语言·javascript·css
言不由衷煦1 小时前
Centos7.x内网环境Jenkins前端打包环境配置
运维·前端·jenkins
Adolf_19931 小时前
JavaScript中的命名导出(暴露)
前端·javascript·react.js
招风的黑耳2 小时前
Spring Web高保真Axure动态交互元件库
前端·spring·axure
橙色小博2 小时前
Python中openpyxl库的基础解析与代码实例
前端·python·excel·openpyxl
xcLeigh2 小时前
HTML5实现简洁的端午节节日网站源码
前端·html5·节日·端午节
托尼沙滩裤2 小时前
Blob文件导出:FileReader是否必需?✨
javascript
大数据魔法师4 小时前
Bootstrap项目 - 个人作品与成就展示网站
前端·bootstrap·html