Lodash源码阅读-lastIndexOf

Lodash 源码阅读-lastIndexOf

概述

lastIndexOf 是 Lodash 中用于在数组中查找元素的方法,它返回找到的最后一个匹配元素的索引,如果没找到则返回 -1。与 JavaScript 原生的 Array.prototype.lastIndexOf 类似,但提供了更好的兼容性和对 NaN 值的特殊处理。

前置学习

依赖函数

  • strictLastIndexOf:Lodash 的内部从右向左查找函数
  • baseFindIndex:Lodash 的基础查找函数
  • baseIsNaN:Lodash 判断 NaN 的内部函数
  • toInteger:Lodash 的整数转换函数

技术知识

  • JavaScript 数组操作
  • NaN 值的特性(NaN !== NaN)
  • 数组索引的正负值处理
  • 类型转换

源码实现

js 复制代码
function lastIndexOf(array, value, fromIndex) {
  var length = array == null ? 0 : array.length;
  if (!length) {
    return -1;
  }
  var index = length;
  if (fromIndex !== undefined) {
    index = toInteger(fromIndex);
    index =
      index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
  }
  return value === value
    ? strictLastIndexOf(array, value, index)
    : baseFindIndex(array, baseIsNaN, index, true);
}

实现思路

lastIndexOf 函数的实现主要分为三个步骤:

  1. 首先处理边界情况,确保数组有效
  2. 然后处理起始位置参数,确保索引在有效范围内
  3. 最后根据查找值的类型(是否为 NaN)选择不同的查找策略

源码解析

1. 边界处理

js 复制代码
var length = array == null ? 0 : array.length;
if (!length) {
  return -1;
}
  • 使用 array == null 同时检查 nullundefined
  • 如果数组为空或无效,直接返回 -1

2. 索引处理

js 复制代码
var index = length;
if (fromIndex !== undefined) {
  index = toInteger(fromIndex);
  index =
    index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
}
  • 默认从数组末尾开始查找
  • 使用 toInteger 确保索引为整数
  • 处理负数索引:从数组末尾开始计算,且不小于 0
  • 处理正数索引:确保不超过数组最大索引

3. 查找策略

js 复制代码
return value === value
  ? strictLastIndexOf(array, value, index)
  : baseFindIndex(array, baseIsNaN, index, true);
  • 利用 NaN !== NaN 的特性判断是否为 NaN
  • 普通值使用 strictLastIndexOf 查找
  • NaN 值使用 baseFindIndex 配合 baseIsNaN 查找

应用场景

  1. 查找数组中最后一个匹配元素的位置
js 复制代码
// 在用户操作历史中查找最后一次点击某个按钮的记录
const userActions = ["click", "scroll", "click", "hover", "click"];
const lastClickIndex = _.lastIndexOf(userActions, "click"); // => 4

// 在商品列表中查找最后一个库存为0的商品
const products = [
  { id: 1, stock: 0 },
  { id: 2, stock: 5 },
  { id: 3, stock: 0 },
];
const lastOutOfStockIndex = _.lastIndexOf(products, { id: 3, stock: 0 }); // => 2
  1. 处理包含 NaN 的数组
js 复制代码
const arr = [1, NaN, 3, NaN];
const lastNaNIndex = _.lastIndexOf(arr, NaN); // 找到最后一个 NaN 的位置
  1. 从指定位置向前查找
js 复制代码
// 在聊天记录中查找最近的特定消息
const messages = ["hello", "world", "hello", "world"];
const lastHelloBeforeIndex = _.lastIndexOf(messages, "hello", 2); // => 0

// 在文件路径中查找最后一个目录分隔符
const path = "src/components/App.vue";
const lastSlashIndex = _.lastIndexOf(path, "/", path.length - 1); // => 13

总结

实现特点

  1. 健壮的空值处理
  2. 灵活的索引计算
  3. 特殊的 NaN 值处理
  4. 模块化的设计思路

设计原则

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