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. 如果有 iteratee 或 comparator,使用相应的方式处理比较逻辑
  4. 对于大型数组,使用 SetCache 优化比较性能
  5. 遍历源数组中的每个元素:
    • 如果元素不在排除值列表中,将其添加到结果数组
    • 使用严格相等比较(SameValueZero)或自定义比较器进行比较

使用示例

基本使用

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

在这个例子中:

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

对象数组比较

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:支持自定义比较器进行比较
相关推荐
楠楠子呀7 分钟前
英语、西语、阿语客户各开一个口:多语言获客的分流方案
开发语言·javascript·ecmascript·跨境电商·whatsapp·营销工具
weifont25 分钟前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化
米柆31 分钟前
HTML5 audio /video 完整事件监听模板
前端·html·html5
半个落月36 分钟前
LangGraph.js 实战:从状态图到分支、循环、检查点与人工中断
javascript·人工智能·langchain
IT_陈寒1 小时前
Vite热更新失效?你可能也踩了这个坑
前端·人工智能·后端
程序员大阳2 小时前
副队长CSS教程(30)–CSS Grid 实战:实现复杂自适应表单布局
前端·css·自适应·grid·表单
Csvn2 小时前
微前端实现
前端
Chrischaan3 小时前
做 AI 塔罗小程序时,我为什么不让大模型自己抽牌:一次上线复盘
前端
骑着蜗牛撵大象3273 小时前
LangChain 工具调用从声明到闭环:给智能体接上真实的手脚
前端
数据掘金3 小时前
百度统计后台页面数据异常?从手动调用时机开始排查
前端