Lodash源码阅读-difference

Lodash 源码阅读-difference

概述

difference 函数是 Lodash 中用于计算数组差集的工具函数。它接收多个数组作为参数,返回一个新数组,其中包含存在于第一个数组中但不存在于其他数组中的元素。差集运算在数据处理、过滤和比较场景中非常有用。

前置学习

依赖函数

  • baseRest:一个转换函数,将剩余参数转换为数组并传递给目标函数
  • isArrayLikeObject:检查值是否为类数组对象(既像数组又是对象,如真实数组、arguments 对象等)
  • baseDifference:实现差集运算的核心函数,处理实际的差集计算逻辑
  • baseFlatten:将嵌套数组扁平化到指定深度的工具函数

技术知识

  • 数组操作:差集等集合运算的基本概念
  • 柯里化与函数组合:Lodash 中函数式编程技巧
  • 剩余参数处理:处理不定数量参数的技术
  • 数组扁平化:处理嵌套数组的方法
  • 类型检查:JavaScript 中的类型判断技巧

源码实现

js 复制代码
var difference = baseRest(function (array, values) {
  return isArrayLikeObject(array)
    ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
    : [];
});

实现思路

difference 函数的实现思路非常简洁但功能强大:

  1. 使用 baseRest 将函数转换为接收剩余参数的形式,并将第一个参数视为源数组,其余参数作为要排除的值
  2. 检查源数组是否为类数组对象,确保输入有效
  3. 使用 baseFlatten 将所有排除值数组扁平化为一个单一的一维数组
  4. 调用 baseDifference 计算第一个数组与扁平化后的排除值数组之间的差集
  5. 如果源数组不是类数组对象,直接返回空数组作为默认结果

源码解析

函数包装与参数处理

js 复制代码
var difference = baseRest(function (array, values) {
  // ...
});

这里使用了 baseRest 函数来包装内部实现。baseRest 类似于 ES6 的剩余参数语法,它将 difference 接收到的所有参数转换成两部分:

  • array:第一个参数,表示要检查的数组
  • values:剩余的所有参数,表示要排除的数组集合

这种设计使 difference 函数可以接受任意数量的数组参数,形如:_.difference(array, values1, values2, ...)

类型检查与边界情况处理

js 复制代码
return isArrayLikeObject(array)
  ? /* 执行差集计算 */
  : [];

函数首先检查 array 是否为类数组对象。这个检查确保了:

  1. 输入参数是对象类型(排除原始值)
  2. length 属性且是非负整数
  3. 不是函数类型

如果第一个参数不是类数组对象,函数直接返回空数组,避免后续处理中的错误。这是处理边界情况的一种优雅方式。

扁平化处理

js 复制代码
baseFlatten(values, 1, isArrayLikeObject, true);

对于 values 参数(剩余的所有数组),函数使用 baseFlatten 进行扁平化处理:

  • values:要扁平化的数组集合
  • 1:扁平化深度为 1,只处理一层嵌套
  • isArrayLikeObject:只扁平化类数组对象
  • true:开启严格模式,只包含通过谓词检查的元素

这一步将所有要排除的数组参数合并成一个一维数组,为差集计算做准备。

差集计算

js 复制代码
baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true));

最后,函数调用 baseDifference 执行实际的差集运算:

  • 第一个参数是源数组 array
  • 第二个参数是扁平化后的所有排除值

baseDifference 会返回一个新数组,其中包含存在于 array 但不存在于扁平化后的 values 中的所有元素。

总结

difference 函数展示了 Lodash 实现函数式工具的精髓:通过组合多个专注于单一任务的小函数,构建出功能强大且易用的高阶函数。这个函数巧妙地结合了:

  1. 函数式设计 :使用 baseRest 实现不定参数处理,符合函数式编程思想
  2. 边界情况处理:通过类型检查确保函数健壮性
  3. 数据转换:使用扁平化处理简化数据结构
  4. 复用核心逻辑 :将核心计算逻辑委托给专用的 baseDifference 函数

从实现上看,difference 考虑了性能和易用性的平衡,通过类型检查减少不必要的计算,同时支持多数组差集运算,为用户提供了灵活的数组差集计算工具。

相关推荐
JarvanMo24 分钟前
借助FlutterFire CLI实现Flutter与Firebase的多环境配置
前端·flutter
Jedi Hongbin37 分钟前
echarts自定义图表--仪表盘
前端·javascript·echarts
凯哥197042 分钟前
Sciter.js指南 - 桌面GUI开发时使用第三方模块
前端
边洛洛42 分钟前
对Electron打包的exe文件进行反解析
前端·javascript·electron
财神爷亲闺女42 分钟前
js 实现pc端鼠标横向拖动滚动
前端
用户20311966009643 分钟前
sheet在SwiftUI中的基本用法
前端
晴殇i44 分钟前
一行代码搞定防抖节流:JavaScript新特性解析
前端·javascript
David凉宸1 小时前
HTML表单(二)
前端