Lodash源码阅读-baseFindIndex

Lodash 源码阅读-baseFindIndex

一、介绍

baseFindIndex 是 Lodash 中一个重要的内部工具函数,它的主要作用是在数组中查找满足特定条件的元素的索引。这个函数非常灵活,因为它接受一个判断函数(predicate)作为参数,可以根据不同的条件来查找元素。它是 Lodash 中很多数组方法的基础,比如 findIndex、findLastIndex、indexOf(查找 NaN 值时)等。

二、源码实现

js 复制代码
function baseFindIndex(array, predicate, fromIndex, fromRight) {
  var length = array.length,
    index = fromIndex + (fromRight ? 1 : -1);

  while (fromRight ? index-- : ++index < length) {
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  return -1;
}

三、实现原理

1. 整体思路

说人话就是:这个函数就像是一个数组探索器,可以从左往右或者从右往左遍历数组,每到一个位置就问一下"这个是我要找的吗?"(通过 predicate 函数判断)。如果是,就说"找到了,在这个位置";如果找完了都没找到,就说"没找到,返回 -1"。

具体来说:

  1. 可以指定从哪个位置开始找(fromIndex)
  2. 可以指定是从左往右找还是从右往左找(fromRight)
  3. 可以自定义判断条件(predicate)
  4. 找到就返回位置,找不到返回 -1

2. 参数说明

  • array:要搜索的数组
  • predicate:判断函数,用来判断是否是要找的元素
  • fromIndex:从哪个位置开始找
  • fromRight:是否从右边开始找(true 表示从右往左,false 表示从左往右)

3. 逐行解析

js 复制代码
var length = array.length,
  index = fromIndex + (fromRight ? 1 : -1);
  • 先记住数组的长度
  • 设置初始索引位置:
    • 如果是从右往左找(fromRight 为 true),则初始索引为 fromIndex + 1
    • 如果是从左往右找(fromRight 为 false),则初始索引为 fromIndex - 1
  • 这样设置是因为在循环开始时会先执行 index-- 或 ++index
js 复制代码
while (fromRight ? index-- : ++index < length) {
  • 这是一个巧妙的循环条件,根据 fromRight 参数决定遍历方向:
    • 如果 fromRight 为 true,则条件是 index--,从右往左遍历
    • 如果 fromRight 为 false,则条件是 ++index < length,从左往右遍历
  • 使用前置递增/递减运算符确保在第一次比较前就更新索引
js 复制代码
if (predicate(array[index], index, array)) {
  return index;
}
  • 对每个元素调用 predicate 函数进行判断
  • predicate 函数接收三个参数:当前元素、索引和整个数组
  • 如果 predicate 返回真值,表示找到了匹配的元素,立即返回当前索引
js 复制代码
return -1;
  • 如果循环结束都没有找到匹配的元素,则返回 -1

四、使用示例

虽然 baseFindIndex 是内部函数,不直接暴露给用户,但我们可以通过 Lodash 的公共函数看到它的作用:

js 复制代码
// 1. 通过 _.findIndex 使用
_.findIndex([1, 2, 3, 4], function (n) {
  return n % 2 === 0;
}); // => 1 (找到第一个偶数的索引)

// 2. 通过 _.findLastIndex 使用
_.findLastIndex([1, 2, 3, 4], function (n) {
  return n % 2 === 0;
}); // => 3 (找到最后一个偶数的索引)

// 3. 通过 _.indexOf 查找 NaN 值时使用
_.indexOf([1, NaN, 3], NaN); // => 1 (内部使用 baseFindIndex 和 baseIsNaN)

// 4. 指定起始位置
_.findIndex(
  [1, 2, 3, 4, 5],
  function (n) {
    return n > 3;
  },
  3
); // => 3 (从索引3开始查找大于3的元素)

// 5. 从右向左查找
// 内部实现中,findLastIndex 会调用 baseFindIndex 并设置 fromRight 为 true
_.findLastIndex([1, 2, 3, 2, 1], function (n) {
  return n === 2;
}); // => 3 (从右往左找到的第一个值为2的元素索引)

五、总结

  1. 方向控制:

    js 复制代码
    while (fromRight ? index-- : ++index < length)

    通过三元运算符巧妙地控制遍历方向,一个函数同时支持从左往右和从右往左查找

  2. 索引初始化:

    js 复制代码
    index = fromIndex + (fromRight ? 1 : -1);

    根据遍历方向预先调整索引,确保循环开始时能正确处理第一个元素

  3. 参数传递:

    js 复制代码
    predicate(array[index], index, array);

    传递完整的上下文信息给 predicate 函数,增强灵活性

  4. 早期返回:

    js 复制代码
    if (predicate(array[index], index, array)) {
      return index;
    }

    找到匹配项立即返回,避免不必要的遍历

相关推荐
lerhxx3 分钟前
AI 应用如何高效优雅地恢复中断?—— "连接解耦 + 状态持久化"
前端·javascript
计算机魔术师5 分钟前
METR 演示 AI 智能体如何篡改 Inspect 评估记录以掩盖不当行为
前端
前端snow39 分钟前
ai agent --- 异步处理之 Rabbit MQ
前端
念何架构之路43 分钟前
zap扩展生态与总结
java·前端·数据库
独孤九剑打醒他1 小时前
【原创开源】【概念设计】源 - 栅 - 漏 - 栅 - 源 横向双栅 MOS,低压交流多值逻辑芯片探索
前端·其他·架构·开源·硬件工程
mantou1321 小时前
我给 AI Agent 做了个「油猴」:让 Claude Code / Codex 直接用你已登录的浏览器
前端·javascript·后端
默_笙1 小时前
🍕 一个主编、三个工种、两本手册:搭一支 AI 调研队
前端·javascript
纸片人2 小时前
Blender 建模 + Three.js 展示:和 AI 一起做一个光储充超充站数字孪生大屏
前端
智能直播2 小时前
网络RTMP拉流不卡顿、声音不同步?一文讲透缓冲区、时间戳与MEDAI V2实战调优
前端
第七页独白2 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库