Lodash源码阅读-sortedIndexOf

Lodash 源码阅读-sortedIndexOf

概述

sortedIndexOf 是 Lodash 里的一个查找函数,它在已排序的数组中查找某个值的位置。跟普通的 indexOf 比起来,它利用了数组已经排好序的特点,用二分查找的方式快速找到目标,速度比普通查找快很多(时间复杂度从 O(n) 降到 O(log n))。

前置学习

依赖函数

  • baseSortedIndex:内部的二分查找函数,用来找值应该插入的位置
  • eq:判断两个值是否相等的函数,能正确处理各种特殊情况(比如 NaN)

技术知识

  • 二分查找:一种在有序数据中快速查找的算法,每次把查找范围缩小一半
  • 相等性比较:JavaScript 中判断值相等的方法和陷阱
  • 边界检查:避免数组索引越界的常见技巧

源码实现

javascript 复制代码
/**
 * This method is like `_.indexOf` except that it performs a binary
 * search on a sorted `array`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Array
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 * @example
 *
 * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
 * // => 1
 */
function sortedIndexOf(array, value) {
  var length = array == null ? 0 : array.length;
  if (length) {
    var index = baseSortedIndex(array, value);
    if (index < length && eq(array[index], value)) {
      return index;
    }
  }
  return -1;
}

实现思路

sortedIndexOf 的思路很直接:

  1. 先检查数组是否为空,空的就直接返回 -1
  2. 用二分查找找到值应该在的位置(第一个大于等于这个值的位置)
  3. 检查一下这个位置上的值是否就是我们要找的值:
    • 是的话,返回这个位置
    • 不是的话,说明数组里没有这个值,返回 -1

这种方法比普通的从头找到尾的方式快多了,特别是在大数组中查找时。

源码解析

边界检查

javascript 复制代码
var length = array == null ? 0 : array.length;
if (length) {
  // 查找逻辑
}
return -1;

先看数组是否为空:

  • 如果传入的 arraynullundefined,就把长度设为 0
  • 只有数组有内容时才进行查找
  • 如果数组是空的,直接返回 -1

这个检查很重要,避免了访问不存在数组的属性而报错。

查找和匹配

javascript 复制代码
var index = baseSortedIndex(array, value);
if (index < length && eq(array[index], value)) {
  return index;
}

这部分是核心逻辑:

  1. baseSortedIndex 找到值应该在的位置
    • 这个函数使用二分查找,找到的是第一个大于等于目标值的位置
  2. 检查两个条件:
    • 找到的位置是否在数组范围内(index < length
    • 该位置的值是否等于要找的值(eq(array[index], value)
  3. 只有当这两个条件都满足时,才返回找到的位置

举个例子说明 index < length 的用处: 假设我们有数组 [1, 3, 5, 7],要查找值 9

  • baseSortedIndex 会返回 4(因为 9 应该插入到数组末尾)
  • 但数组长度只有 4,所以 index < length 条件不满足(4 < 4 为 false)
  • 这就避免了访问 array[4](不存在的元素),防止出现越界错误
  • 函数会直接返回 -1,表示没找到

这个检查确保了即使要查找的值比数组中所有元素都大,函数也能正确处理。

eq 函数比普通的 === 更智能,能正确处理 NaN 等特殊情况。

返回结果

javascript 复制代码
return -1;

如果没找到匹配的值,就返回 -1,这和 JavaScript 原生的 indexOf 行为一致。

总结

sortedIndexOf 这个小函数展示了数据结构和算法的重要性:

  1. 利用数据特性

    • 知道数组已排序后,可以用更高效的算法
    • 二分查找把时间复杂度从 O(n) 降到 O(log n)
  2. 健壮性设计

    • 做好边界检查和异常处理
    • eq 函数解决 JavaScript 相等比较的各种坑
  3. API 设计

    • 保持与原生 indexOf 相同的接口风格
    • 函数名清晰地表明它的用途和适用条件

这种专门针对特定场景优化的函数,是 Lodash 这类工具库价值的体现 ------ 让常见操作变得更简单、更高效。

相关推荐
崔庆才丨静觅23 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax