Lodash源码阅读-dropWhile

Lodash 源码阅读-dropWhile

概述

dropWhile 函数创建一个新数组,从原数组开头删除满足条件的元素,直到遇到第一个不满足条件的元素为止。它是一个动态过滤函数,根据元素内容决定删除数量,而不是简单地删除固定数量。

前置学习

依赖函数

  • baseWhile:内部工具函数,实现基于条件的数组切片核心逻辑
  • getIteratee:获取迭代函数,支持多种简写形式

技术知识

  • 高阶函数:函数作为参数的使用方式
  • 谓词函数:返回布尔值的条件判断函数
  • 迭代器简写:Lodash 支持的迭代器多种形式
  • 数组切片:条件性数组切片操作
  • 短路求值:条件满足时提前结束迭代

源码实现

javascript 复制代码
/**
 * Creates a slice of `array` excluding elements dropped from the beginning.
 * Elements are dropped until `predicate` returns falsey. The predicate is
 * invoked with three arguments: (value, index, array).
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to query.
 * @param {Function} [predicate=_.identity] The function invoked per iteration.
 * @returns {Array} Returns the slice of `array`.
 * @example
 *
 * var users = [
 *   { 'user': 'barney',  'active': false },
 *   { 'user': 'fred',    'active': false },
 *   { 'user': 'pebbles', 'active': true }
 * ];
 *
 * _.dropWhile(users, function(o) { return !o.active; });
 * // => objects for ['pebbles']
 *
 * // The `_.matches` iteratee shorthand.
 * _.dropWhile(users, { 'user': 'barney', 'active': false });
 * // => objects for ['fred', 'pebbles']
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.dropWhile(users, ['active', false]);
 * // => objects for ['pebbles']
 *
 * // The `_.property` iteratee shorthand.
 * _.dropWhile(users, 'active');
 * // => objects for ['barney', 'fred', 'pebbles']
 */
function dropWhile(array, predicate) {
  return array && array.length
    ? baseWhile(array, getIteratee(predicate, 3), true)
    : [];
}

实现思路

dropWhile 函数的实现围绕两个关键点:输入验证和条件删除。

首先检查数组是否有效,如果无效则返回空数组。若有效,则调用 baseWhile 函数,传入数组、处理过的迭代函数和 true 参数(表示执行"删除"而非"保留"操作)。baseWhile 从数组开头开始迭代,持续删除满足条件的元素,直到遇到第一个不满足条件的元素,然后返回剩余部分。

源码解析

参数验证与空值处理

javascript 复制代码
return array && array.length ? ... : [];

这行代码检查输入数组是否存在且非空:

  • 如果数组为 nullundefined 或空数组,直接返回空数组 []
  • 使用短路逻辑 && 简洁地实现多条件检查
  • 这确保了函数对各种边缘情况的安全处理

迭代器转换

javascript 复制代码
getIteratee(predicate, 3);

getIteratee 函数将各种类型的 predicate 转换为标准函数:

  • 数字 3 表示迭代函数接收三个参数:值、索引、原数组
  • 如果 predicate 已是函数,直接使用
  • 如果是对象 {user: 'barney'},转为属性匹配函数
  • 如果是数组 ['active', false],转为属性值匹配函数
  • 如果是字符串 'active',转为属性访问函数

这种转换让 dropWhile 支持多种简写形式,如:

javascript 复制代码
// 函数形式
_.dropWhile(users, (user) => !user.active);

// 对象匹配形式
_.dropWhile(users, { user: "barney", active: false });

// 属性-值匹配形式
_.dropWhile(users, ["active", false]);

// 属性访问形式
_.dropWhile(users, "active");

baseWhile 调用

javascript 复制代码
baseWhile(array, getIteratee(predicate, 3), true);

这是函数核心,调用 baseWhile 执行实际删除:

  • 第一个参数是要处理的数组
  • 第二个参数是转换后的谓词函数
  • 第三个参数 true 指定这是一个"删除"操作

baseWhile 的工作流程:

  1. 从数组开头开始迭代
  2. 对每个元素应用谓词函数
  3. 持续迭代直到谓词返回 false
  4. 返回从第一个不满足条件的元素到数组末尾的切片

例如,对于数组 [2, 4, 6, 3, 8] 和条件 x => x % 2 === 0(是否为偶数):

  • 元素 2:满足条件,继续
  • 元素 4:满足条件,继续
  • 元素 6:满足条件,继续
  • 元素 3:不满足条件,停止
  • 返回 [3, 8](从第一个不满足条件的元素开始)

总结

dropWhile 函数体现了几个核心设计原则:

  1. 单一职责:专注于一个明确任务(条件删除),不包含多余功能
  2. 组合性:通过组合内部函数实现功能,增强代码复用
  3. 声明式编程:通过指定"条件"而非详细步骤,使代码更易理解
  4. 不可变性:不修改原数组,返回新数组,避免副作用
  5. 灵活性:支持多种谓词表达方式,适应不同使用场景

这个设计让我们在日常开发中能够用简洁代码表达复杂的条件过滤逻辑,提高代码可读性和可维护性。

相关推荐
清岚_lxn3 小时前
原生SSE实现AI智能问答+Vue3前端打字机流效果
前端·javascript·人工智能·vue·ai问答
ZoeLandia3 小时前
Element UI 设置 el-table-column 宽度 width 为百分比无效
前端·ui·element-ui
橘子味的冰淇淋~3 小时前
解决 vite.config.ts 引入scss 预处理报错
前端·vue·scss
萌萌哒草头将军5 小时前
💎这么做,cursor 生成的代码更懂你!💎
javascript·visual studio code·cursor
小小小小宇5 小时前
V8 引擎垃圾回收机制详解
前端
lauo6 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
拉不动的猪6 小时前
设计模式之------单例模式
前端·javascript·面试
一袋米扛几楼986 小时前
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
前端·react.js·前端框架
Alt.96 小时前
SpringMVC基础二(RestFul、接收数据、视图跳转)
java·开发语言·前端·mvc
进取星辰7 小时前
1、从零搭建魔法工坊:React 19 新手村生存指南
前端·react.js·前端框架