Lodash源码阅读-pullAllBy

Lodash 源码阅读-pullAllBy

概述

pullAllBy 是 Lodash 中的一个数组操作函数,用于根据指定的迭代器函数比较标准,从数组中移除特定元素。与 pullAll 不同的是,它允许通过自定义迭代器来决定如何比较元素,使其能够处理更复杂的数据结构。该函数会直接修改原数组(具有副作用),并返回修改后的数组。

前置学习

依赖函数

  • basePullAll:内部核心函数,实现数组元素移除的底层逻辑
  • getIteratee:获取适当的迭代器函数,支持多种输入格式(函数、字符串、对象等)

技术知识

  • 数组操作:数组的修改和引用
  • 高阶函数:函数作为参数传递
  • 迭代器模式:使用迭代器函数处理集合元素
  • 函数参数校验:参数有效性检查

源码实现

js 复制代码
function pullAllBy(array, values, iteratee) {
  return array && array.length && values && values.length
    ? basePullAll(array, values, getIteratee(iteratee, 2))
    : array;
}

实现思路

pullAllBy 的实现非常简洁明了。它首先检查源数组和目标值数组是否都存在且非空,然后调用 basePullAll 函数执行实际的移除操作,同时传入由 getIteratee 处理后的迭代器函数。这种设计将函数主体的复杂性委托给专门的内部函数,使公共 API 保持简洁。

核心思路是:

  1. 验证输入数组的有效性
  2. 处理迭代器参数,使其标准化
  3. 调用内部函数完成实际工作
  4. 返回修改后的原数组

源码解析

函数签名:

js 复制代码
function pullAllBy(array, values, iteratee)
  • array:要修改的原始数组
  • values:包含要移除元素的数组
  • iteratee:迭代器函数,用于生成比较标准

函数实现细节:

js 复制代码
return array && array.length && values && values.length
  ? basePullAll(array, values, getIteratee(iteratee, 2))
  : array;

这行代码包含了几个关键逻辑:

  1. 输入验证array && array.length && values && values.length

    • 检查 arrayvalues 是否都是有效的非空数组
    • 如果任一条件不满足,直接返回原数组,避免不必要的处理
  2. 迭代器处理getIteratee(iteratee, 2)

    • 使用 getIteratee 将用户提供的 iteratee 转换为标准函数
    • 数字 2 表示迭代器函数的参数数量(arity)
    • 这允许用户传入不同类型的迭代器,如字符串属性名、函数等
  3. 核心调用basePullAll(array, values, ...)

    • 调用内部函数 basePullAll 执行实际的元素移除操作
    • 将处理后的迭代器作为第三个参数传入

pullAllBy 函数的关键特性是它支持多种形式的迭代器参数:

  • 函数:直接使用用户提供的函数
  • 字符串:将其视为属性路径,创建一个提取该属性的函数
  • 对象:创建一个检查属性匹配的函数

这种灵活性使 pullAllBy 能够适应各种使用场景。

应用场景

  1. 对象数组过滤:根据对象的特定属性移除元素
js 复制代码
// 从用户列表中移除指定ID的用户
let users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 3, name: "Charlie" },
];
_.pullAllBy(users, [{ id: 1 }, { id: 3 }], "id");
// users 现在是 [{ id: 2, name: "Bob" }]
  1. 基于转换后的值比较:通过迭代器转换元素后再比较
js 复制代码
// 忽略小数部分比较数字
let numbers = [1.2, 2.3, 3.7, 4.5, 5.1];
_.pullAllBy(numbers, [1.8, 3.2, 5.9], Math.floor);
// numbers 现在是 [2.3, 4.5]
// 因为Math.floor(1.2)===Math.floor(1.8),Math.floor(3.7)===Math.floor(3.2),Math.floor(5.1)===Math.floor(5.9)
js 复制代码
// 根据数字的十位数移除元素
let scores = [22, 35, 47, 58, 73, 86];
_.pullAllBy(scores, [31, 42, 79], (num) => Math.floor(num / 10));
// scores 现在是 [47, 58, 86]
// 22和31、35和42、73和79的十位数相同,所以被移除
  1. 数据清洗:移除具有特定特征的元素
js 复制代码
// 从产品列表中移除所有停产的产品
let products = [
  { name: "Laptop", status: "active" },
  { name: "Phone", status: "discontinued" },
  { name: "Tablet", status: "active" },
  { name: "Camera", status: "discontinued" },
];
_.pullAllBy(products, [{ status: "discontinued" }], "status");
// products 现在只包含状态为active的产品

总结

pullAllBy 函数展示了 Lodash 库中常见的几个设计原则:

  1. 委托模式:将复杂逻辑委托给专门的内部函数,保持公共 API 的简洁
  2. 参数灵活性:支持多种类型的迭代器参数,提高函数的适用性
  3. 输入验证:在执行操作前验证参数的有效性,增强代码健壮性
  4. 一致返回:不论是否执行操作,始终返回原数组,维持接口一致性
  5. 副作用明确:函数文档明确说明该函数会修改原数组

pullAllBy 虽然实现简单,但通过与其他内部函数(如 basePullAllgetIteratee)的组合,提供了强大的功能。它允许用户以灵活的方式指定元素比较标准,使得从数组中移除元素的操作既直观又强大。这种"简单接口,复杂实现"的设计思想,使得 Lodash 库易于使用但功能强大。

相关推荐
利刃之灵14 分钟前
02-HTML结构
前端·html
小纯洁w14 分钟前
Vue和React项目中,统一监听页面错误需要结合框架提供的错误处理机制与JavaScript原生方法
javascript·vue.js·react.js
Hopebearer_20 分钟前
理解 React 的 useEffect
前端·javascript·react.js·前端框架
excel2 小时前
webpack 检出图 第 十 节 lib/ChunkGraph.js
前端
好_快2 小时前
Lodash源码阅读-parent
前端·javascript·源码阅读
shmily ....2 小时前
前端实战:基于 Vue 与 QRCode 库实现动态二维码合成与下载功能
前端·vue.js
excel2 小时前
webpack 检出图 第 九 节 lib/ChunkGraph.js
前端
好_快2 小时前
Lodash源码阅读-pullAllWith
前端·javascript·源码阅读
web守墓人6 小时前
【gpt生成-其一】以go语言为例,详细描述一下 :语法规范BNF/EBNF形式化描述
前端·gpt·golang