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
函数的设计非常直接,它通过以下步骤工作:
- 从指定的起始位置(
fromIndex
)开始遍历数组 - 对每个元素,使用自定义比较器函数(
comparator
)与目标值进行比较 - 当比较器返回
true
时,表示找到匹配元素,返回当前索引 - 如果遍历完整个数组都没有找到匹配元素,则返回
-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
六、总结
-
灵活性提升 :通过允许自定义比较器,
baseIndexOfWith
大幅提升了数组查找的灵活性,能够应对各种复杂场景。 -
函数设计:函数设计简洁明了,参数排列逻辑清晰,遵循了"最后一个参数是回调"的惯例。
-
函数式编程特性:接收函数作为参数,展现了函数式编程中高阶函数的特点。