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:支持自定义比较器进行比较
相关推荐
张开心_kx5 分钟前
面试官又问我受控组件和非受控组件?
前端·javascript·react.js
stanny6 分钟前
MCP(下)——跟着官方实现一个MCP
javascript·mcp
brzhang8 分钟前
流量大了就加机器?太 Low 了!负载均衡的这些高级玩法,让你部署、测试、安全一步到位!
前端·后端·架构
LavenderLee8 分钟前
CSS+JS实现融球+跟随鼠标效果
前端
我是哪吒9 分钟前
分布式微服务系统架构第122集:NestJS是一个用于构建高效、可扩展的服务器端应用程序的开发框架
前端·后端·面试
学了就忘10 分钟前
JavaScript 异步编程与请求取消全指南
开发语言·javascript·ecmascript
凯哥197011 分钟前
Sciter.js 指南 - GUI的窗口管理特性详解
前端
秋天的一阵风12 分钟前
Webpack 插件开发:为 Vue.js 应用实现图片预加载
前端·vue.js·webpack
努力学习的小刘13 分钟前
JS实现并发控制、请求合并、数据缓存
前端
LengineerC13 分钟前
React添加路由切换过渡动画
前端