Lodash源码阅读-baseIndexOfWith

Lodash 源码阅读-baseIndexOfWith

一、功能概述

baseIndexOfWith 是 Lodash 中的一个内部基础工具函数,它提供了一个更灵活的数组元素查找机制。与 baseIndexOf 不同,该函数允许自定义比较器(comparator)来判断元素是否匹配,这使得它能够支持复杂的相等性判断。

二、前置学习

在深入理解 baseIndexOfWith 函数之前,建议先了解以下相关概念:

  • 比较器函数(Comparator):接收两个参数并返回布尔值的函数,用于确定两个值是否相等
  • 高阶函数:接收函数作为参数的函数
  • baseIndexOf:基础的索引查找函数

三、源码实现

js 复制代码
/**
 * This function is like `baseIndexOf` except that it accepts a comparator.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @param {number} fromIndex The index to search from.
 * @param {Function} comparator The comparator invoked per element.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseIndexOfWith(array, value, fromIndex, comparator) {
  var index = fromIndex - 1,
    length = array.length;

  while (++index < length) {
    if (comparator(array[index], value)) {
      return index;
    }
  }
  return -1;
}

四、实现原理

1. 整体思路

baseIndexOfWith 函数的设计非常直接,它通过以下步骤工作:

  1. 从指定的起始位置(fromIndex)开始遍历数组
  2. 对每个元素,使用自定义比较器函数(comparator)与目标值进行比较
  3. 当比较器返回 true 时,表示找到匹配元素,返回当前索引
  4. 如果遍历完整个数组都没有找到匹配元素,则返回 -1

相比 baseIndexOf,baseIndexOfWith 的核心优势在于它的灵活性:你可以自定义如何判断两个值是否相等,而不局限于严格相等(===)或特定的 NaN 处理。

2. 参数说明

  • array:要搜索的数组
  • value:要查找的值
  • fromIndex:从哪个位置开始查找(索引值)
  • comparator:比较器函数,接收两个参数(当前元素和要查找的值),返回布尔值

3. 逐行解析

js 复制代码
var index = fromIndex - 1,
  length = array.length;
  • 初始化索引变量,设为 fromIndex - 1,是因为后续使用前置递增(++index)
  • 缓存数组长度,避免在循环中重复获取
js 复制代码
while (++index < length) {
  • 使用前置递增操作符(++index)实现从 fromIndex 开始的遍历
  • 遍历直到数组末尾
js 复制代码
if (comparator(array[index], value)) {
  return index;
}
  • 调用自定义比较器函数,比较当前元素与目标值
  • 如果比较器返回 true,表示找到匹配,立即返回当前索引
js 复制代码
return -1;
  • 如果循环结束后没有找到匹配元素,返回 -1,这是数组查找方法的标准约定

五、使用示例

虽然 baseIndexOfWith 是 Lodash 的内部函数,但我们可以模拟其用法以理解其功能:

js 复制代码
// 1. 基本使用 - 自定义相等性比较
const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 2 }];
const customComparator = (element, target) => element.id === target.id;

baseIndexOfWith(array, { id: 2 }, 0, customComparator); // => 1
baseIndexOfWith(array, { id: 2 }, 2, customComparator); // => 3 (从索引2开始查找)

// 2. 模糊匹配 - 字符串包含关系
const strings = ["apple", "banana", "cherry", "date"];
const includesComparator = (element, search) => element.includes(search);

baseIndexOfWith(strings, "an", 0, includesComparator); // => 1 (banana 包含 "an")

// 3. 数值范围比较
const numbers = [10, 20, 30, 40, 50];
const rangeComparator = (element, range) =>
  element >= range[0] && element <= range[1];

baseIndexOfWith(numbers, [25, 45], 0, rangeComparator); // => 2 (30在25-45范围内)

// 4. 使用Lodash的自带比较器
// 假设我们使用 _.isEqual 作为比较器
const deepComparator = _.isEqual;
const complexArray = [
  [1, 2],
  [3, 4],
  [5, 6],
];

baseIndexOfWith(complexArray, [3, 4], 0, deepComparator); // => 1

六、总结

  1. 灵活性提升 :通过允许自定义比较器,baseIndexOfWith 大幅提升了数组查找的灵活性,能够应对各种复杂场景。

  2. 函数设计:函数设计简洁明了,参数排列逻辑清晰,遵循了"最后一个参数是回调"的惯例。

  3. 函数式编程特性:接收函数作为参数,展现了函数式编程中高阶函数的特点。

相关推荐
miss38 分钟前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
AiMan1 小时前
腾讯ima还是不可以导出左侧所有对话,只能单条导出,方法不对吗
前端
去伪存真1 小时前
并发量一高就装死?Agent 全链路“防猝死”手册
前端·agent
Moment1 小时前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
AiMan2 小时前
先确认能不能一次把Microsofat Copilot所有内容打包一个文件导出
前端
总要学点什么2 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技2 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥2 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易3 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭3 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter