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 考虑了性能和易用性的平衡,通过类型检查减少不必要的计算,同时支持多数组差集运算,为用户提供了灵活的数组差集计算工具。

相关推荐
cypking15 分钟前
Vue 3 + Vite + Router + Pinia + Element Plus + Monorepo + qiankun 构建企业级中后台前端框架
前端·javascript·vue.js
San30.26 分钟前
ES6+ 新特性解析:让 JavaScript 开发更优雅高效
开发语言·javascript·es6
雨雨雨雨雨别下啦1 小时前
【从0开始学前端】vue3简介、核心代码、生命周期
前端·vue.js·vue
simon_93491 小时前
受够了压缩和收费?我作为一个码农,手撸了一款无限容量、原图直出的瀑布流相册!
前端
e***87702 小时前
windows配置永久路由
android·前端·后端
u***27612 小时前
TypeScript 与后端开发Node.js
javascript·typescript·node.js
星空的资源小屋2 小时前
跨平台下载神器ArrowDL,一网打尽所有资源
javascript·笔记·django
Dorcas_FE3 小时前
【tips】动态el-form-item中校验的注意点
前端·javascript·vue.js
小小前端要继续努力3 小时前
前端新人怎么更快的融入工作
前端
八月ouc3 小时前
解密JavaScript模块化演进:从IIFE到ES Module,深入理解现代前端工程化基石
javascript·es6·模块化·cmd·commonjs·amd·iife