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:支持自定义比较器进行比较
相关推荐
江南19977 分钟前
JavaScript深入学习系列----函数篇上
javascript
独立开阀者_FwtCoder14 分钟前
三行CSS代码把网页像素化
前端·javascript·github
用户377434860022026 分钟前
从渲染集合到模块学习
前端
安心不心安27 分钟前
React状态管理——redux-saga异步操作
前端·javascript·react.js
猩猩程序员30 分钟前
bzip2 crate 从 C 切换为 100% Rust 实现
前端
500佰30 分钟前
总结前端三年 理想滚烫与现实的冰冷碰撞
前端
全栈小531 分钟前
【前端】Vue3+elementui+ts,给标签设置样式属性style时,提示type check failed for prop,再次请出DeepSeek来解答
前端·elementui
哪 吒32 分钟前
突破亚马逊壁垒,Web Unlocker API 助您轻松获取数据
前端·网络·python·网络安全
岸边的风33 分钟前
JavaScript篇:【前端必备】数组方法大全:从‘会写’到‘玩出花’,你掌握几个?
开发语言·前端·javascript
三天不学习34 分钟前
一文了解Blob文件格式,前端必备技能之一
前端·blob