Lodash源码阅读-without

Lodash 源码阅读-without

概述

without 函数用于创建一个新数组,其中排除了所有给定的值。它使用 SameValueZero 算法进行相等性比较,这意味着它可以正确处理 NaN 等特殊值。与 _.pull 不同,without 不会修改原数组,而是返回一个新数组。

前置学习

依赖函数

  • baseRest:用于处理不定参数,类似 ES6 的剩余参数功能
  • isArrayLikeObject:检查值是否为类数组对象
  • baseDifference:计算数组差集的基础实现

技术知识

  • SameValueZero :ECMAScript 规范中的比较算法,与 === 类似但能正确处理 NaN
  • 不定参数处理:处理可变数量的函数参数
  • 数组差集:从一个数组中移除另一个数组中存在的元素

源码实现

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

实现思路

without 函数的实现非常简洁,主要分为三个步骤:

  1. 使用 baseRest 包装函数,处理不定参数,将第一个参数识别为 array,其余参数收集到 values 数组中
  2. 检查 array 是否为类数组对象,确保输入有效
  3. 如果输入有效,调用 baseDifference 计算差集;否则返回空数组

这种实现方式既简洁又高效,可以处理各种输入情况,同时保持了函数的健壮性。

源码解析

函数签名和参数处理

js 复制代码
var without = baseRest(function(array, values) {

without 使用 baseRest 高阶函数进行包装,这使它能够接收不定数量的参数:

  • 第一个参数 array 是要处理的数组
  • 剩余的所有参数会被收集到 values 数组中

baseRest 的作用类似于 ES6 的剩余参数 ...values,但它提供了更多的灵活性和兼容性。

类型检查和结果计算

js 复制代码
return isArrayLikeObject(array) ? baseDifference(array, values) : [];

这部分代码执行两个关键操作:

  1. 类型检查 :使用 isArrayLikeObject 判断 array 是否为类数组对象

    • 类数组对象包括数组、arguments 对象、DOM 集合等
    • 这个检查确保了函数能安全处理各种输入
  2. 差集计算

    • 如果 array 是类数组对象,调用 baseDifference(array, values) 计算差集
    • 如果 array 不是类数组对象,直接返回空数组 [],避免程序异常

baseDifference 的工作原理

baseDifference 是 Lodash 内部的一个函数,用于计算数组差集。它的工作流程如下:

  1. 初始化结果数组 result = []
  2. 如果源数组为空,直接返回空结果
  3. 如果有 iterateecomparator,使用相应的方式处理比较逻辑
  4. 对于大型数组,使用 SetCache 优化比较性能
  5. 遍历源数组中的每个元素:
    • 如果元素不在排除值列表中,将其添加到结果数组
    • 使用严格相等比较(SameValueZero)或自定义比较器进行比较

使用示例

基本使用

js 复制代码
_.without([2, 1, 2, 3], 1, 2);
// => [3]

在这个例子中:

  • 源数组是 [2, 1, 2, 3]
  • 要排除的值是 12
  • 结果是 [3],即源数组中所有非 12 的元素

对象数组比较

js 复制代码
var object1 = { a: 1 };
var object2 = { b: 2 };
var array = [object1, object2];

_.without(array, { a: 1 });
// => [object1, object2],因为使用严格相等比较

_.without(array, object1);
// => [object2],成功移除了 object1

这个例子展示了 without 使用严格相等比较的特性:

  • 即使 { 'a': 1 }object1 内容相同,但它们是不同的对象引用
  • 只有直接引用 object1 才能成功排除它

总结

without 函数提供了一种简便的方式来创建排除特定值的新数组。其主要特点包括:

  1. 不可变性:不修改原数组,而是返回新数组,符合函数式编程原则
  2. 灵活的参数:支持排除多个值,提高了使用便利性
  3. 严格比较:使用 SameValueZero 算法进行比较,确保准确性
  4. 类型安全:对输入进行类型检查,增强了函数的健壮性

虽然 without 的功能可以通过 filter 实现,但它提供了更简洁的 API,特别适合从数组中快速排除一些已知值的场景。

如果需要更复杂的排除逻辑,可以考虑使用 Lodash 的其他方法:

  • _.difference:排除另一个数组中的所有值
  • _.differenceBy:支持通过迭代器进行值转换后比较
  • _.differenceWith:支持自定义比较器进行比较
相关推荐
yanlele5 分钟前
【实践篇】【01】我用做了一个插件, 点击复制, 获取当前文章为 Markdown 文档
前端·javascript·浏览器
爱编程的喵8 分钟前
React useContext 深度解析:告别组件间通信的噩梦
前端·react.js
LeeAt9 分钟前
手把手教你构建自己的MCP服务器并把它连接到你的Cursor
javascript·cursor·mcp
前端风云志1 小时前
TypeScript枚举类型应用:前后端状态码映射的最简方案
javascript
望获linux1 小时前
【实时Linux实战系列】多核同步与锁相(Clock Sync)技术
linux·前端·javascript·chrome·操作系统·嵌入式软件·软件
魂祈梦1 小时前
rsbuild的环境变量
前端
赫本的猫1 小时前
告别生命周期!用Hooks实现更优雅的React开发
前端·react.js·面试
LaoZhangAI1 小时前
Browser MCP完全指南:5分钟掌握AI浏览器自动化新范式(2025最新)
前端·后端
咸鱼青菜好好味1 小时前
node的项目实战相关3-部署
前端
赫本的猫1 小时前
React中的路由艺术:用react-router-dom实现无缝页面切换
前端·react.js·面试