Lodash 源码阅读-indexOf
一、介绍
indexOf
是 Lodash 中用于在数组中查找元素的方法,它返回找到的第一个匹配元素的索引,如果没找到则返回 -1。与 JavaScript 原生的 Array.prototype.indexOf
类似,但 Lodash 版本提供了更好的兼容性和对 NaN
值的特殊处理。
前置学习
在深入理解 indexOf
函数之前,建议先了解以下相关概念:
-
baseIndexOf:Lodash 的内部查找函数
-
toInteger:Lodash 的整数转换函数
二、源码实现
js
function indexOf(array, value, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
return baseIndexOf(array, value, index);
}
三、实现原理
1. 整体思路
indexOf
函数的实现思路可以概括为:
- 处理边界情况(空数组、null/undefined)
- 处理起始位置参数(默认值、负数索引)
- 调用
baseIndexOf
执行实际的查找逻辑 - 返回找到的索引或 -1
2. 参数说明
array
:要搜索的数组value
:要查找的值fromIndex
:开始搜索的位置(索引),可选
3. 逐行解析
js
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
- 获取数组长度,如果数组为
null
或undefined
,则设为 0 - 如果数组长度为 0,直接返回 -1(优化处理)
js
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
- 处理
fromIndex
参数 - 如果未提供,默认为 0
- 使用
toInteger
函数确保fromIndex
是整数 - 如果是负数,则从数组末尾开始计算位置,且不小于 0
js
return baseIndexOf(array, value, index);
- 调用
baseIndexOf
执行实际的查找逻辑
四、使用示例
js
// 基本使用
_.indexOf([1, 2, 3, 4], 2); // => 1
_.indexOf([1, 2, 3, 4], 5); // => -1
// 指定起始位置
_.indexOf([1, 2, 3, 1, 2, 3], 2, 2); // => 4
// 处理 NaN 值(这是与原生 indexOf 的主要区别)
_.indexOf([1, NaN, 3], NaN); // => 1
[1, NaN, 3].indexOf(NaN); // => -1 (原生方法找不到 NaN)
// 负数索引
_.indexOf([1, 2, 3, 4], 2, -2); // => -1 (从倒数第二个元素开始查找)
_.indexOf([1, 2, 3, 4], 3, -2); // => 2
// 处理 null/undefined
_.indexOf(null, 1); // => -1
_.indexOf(undefined, 1); // => -1
五、与原生 indexOf 的区别
-
NaN 处理 :Lodash 的
indexOf
可以找到数组中的NaN
值,而原生Array.prototype.indexOf
不行 -
兼容性:Lodash 的实现考虑了更多的边界情况和浏览器兼容性问题
-
fromIndex 处理:对负数索引的处理更加健壮
六、总结
-
安全的空值处理:
jsvar length = array == null ? 0 : array.length;
使用宽松相等检查 null 和 undefined,避免报错
-
模块化设计:
jsreturn baseIndexOf(array, value, index);
将核心查找逻辑抽离到专门的函数中
-
负索引处理:
jsindex = nativeMax(length + index, 0);
确保负索引转换为有效的数组索引,且不小于 0
-
早期返回优化:
jsif (!length) { return -1; }
对空数组进行快速处理,避免不必要的计算