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 这类工具库价值的体现 ------ 让常见操作变得更简单、更高效。

相关推荐
天天扭码1 分钟前
LeetCode 题解 | 1.两数之和(最优解)
前端·javascript·算法
冉冉同学4 分钟前
【HarmonyOS NEXT】解决微信浏览器无法唤起APP的问题
android·前端·harmonyos
广龙宇7 分钟前
【Web API系列】Web Shared Storage API之WorkletSharedStorage深度解析与实践指南
前端
逍遥德13 分钟前
前端工程化-包管理NPM-package.json 和 package-lock.json 详解
前端·npm·json
一只小风华~14 分钟前
Web前端 (CSS篇)
前端·css·html·html5
HelloRevit18 分钟前
npm install 版本过高引发错误,请添加 --legacy-peer-deps
前端·npm·node.js
工九度20 分钟前
2025前端社招最新面试题汇总- 场景题篇
前端·javascript
AronTing20 分钟前
状态模式:有限状态机在电商订单系统中的设计与实现
前端·设计模式·面试
这可不简单21 分钟前
git push 受阻,原是未拉取代码惹的祸
前端·git·面试
啊吧啊吧曾小白24 分钟前
封装 downloadFile 函数,从服务器下载文件
前端·javascript·面试