Lodash源码阅读-basePullAt

Lodash 源码阅读-basePullAt

概述

basePullAt 是 Lodash 内部的工具函数,用于从数组中移除指定索引位置的元素。它是 _.pullAt 方法的底层实现,支持同时移除多个索引位置的元素,并且会修改原数组。

前置学习

依赖函数

  • isIndex: 判断一个值是否为有效的数组索引
  • baseUnset: 移除对象属性的内部方法(用于非数字索引)
  • splice: JavaScript 原生数组方法,用于删除数组元素

技术知识

  • 数组修改操作: 原地修改数组的方法
  • 函数绑定 : 使用 call 方法调用函数并绑定 this
  • 稀疏数组: JavaScript 中的非连续索引数组
  • 索引处理: 数组索引与对象属性的区别

源码实现

js 复制代码
function basePullAt(array, indexes) {
  var length = array ? indexes.length : 0,
    lastIndex = length - 1;

  while (length--) {
    var index = indexes[length];
    if (length == lastIndex || index !== previous) {
      var previous = index;
      if (isIndex(index)) {
        splice.call(array, index, 1);
      } else {
        baseUnset(array, index);
      }
    }
  }
  return array;
}

实现思路

basePullAt 函数的设计思路非常巧妙:

  1. 从后向前遍历索引数组,这样在删除元素时不会影响后续元素的索引位置
  2. 使用 isIndex 判断索引是否为有效的数组索引
  3. 对于有效的数组索引,使用原生的 splice 方法删除元素
  4. 对于非数字索引(对象属性),使用 baseUnset 方法删除
  5. 跳过重复的索引,避免多次尝试删除同一位置的元素
  6. 返回修改后的原数组

这种实现方式保证了高效的数组元素删除,并且处理了各种边界情况。

源码解析

让我们逐步解析 basePullAt 函数的实现:

js 复制代码
function basePullAt(array, indexes) {
  var length = array ? indexes.length : 0,
      lastIndex = length - 1;

首先,函数检查 array 是否存在,如果存在,则获取 indexes 数组的长度;如果不存在,则将长度设为 0。同时计算出最后一个索引的位置。

js 复制代码
while (length--) {
  var index = indexes[length];

函数使用了从后向前的遍历方式(length--),这样当删除前面的元素时,不会影响后面元素的索引位置。在每次循环中,获取当前要处理的索引值。

js 复制代码
if (length == lastIndex || index !== previous) {
  var previous = index;

这段代码检查当前索引是否是最后一个索引或者与前一个处理的索引不同。这是为了避免重复处理相同的索引。如果 indexes 数组中包含重复的索引,只有第一次遇到时才会执行删除操作。

js 复制代码
if (isIndex(index)) {
  splice.call(array, index, 1);
} else {
  baseUnset(array, index);
}

根据索引类型选择不同的删除方法:

  • 如果是有效的数组索引(通过 isIndex 函数判断),使用 splice.call(array, index, 1) 方法从数组中删除该位置的元素。
  • 如果不是有效的数组索引(可能是字符串属性名),使用 baseUnset(array, index) 方法删除该属性。
js 复制代码
}
}
return array;

最后,函数返回修改后的原数组。

应用示例

js 复制代码
var array = ["a", "b", "c", "d"];
basePullAt(array, [1, 3]);
// 移除索引 1 和 3 的元素
// array 变成 ['a', 'c']

var obj = { 0: "a", 1: "b", foo: "bar" };
basePullAt(obj, [1, "foo"]);
// 移除索引 1 和属性 'foo'
// obj 变成 { '0': 'a' }

总结

basePullAt 函数是一个精巧的数组元素删除工具,它具有以下几个设计亮点:

  1. 逆序遍历: 从后向前删除元素,避免索引位置变化导致的问题。
  2. 类型判断: 区分处理数组索引和对象属性,使用不同的删除方法。
  3. 去重处理: 避免对重复索引进行多次操作,提高效率。
  4. 原地修改: 直接修改原数组,不创建新数组,节省内存。

这个函数体现了 Lodash 在处理数组操作时的细致考量,包括性能优化和边界情况的处理。理解这种实现方式对于我们设计自己的数组操作函数也有很大的启发。

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端