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. 灵活性:支持多种谓词表达方式,适应不同使用场景

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

相关推荐
小菜今天没吃饱5 分钟前
DVWA-XSS(Reflected)
前端·xss·dvwa
孟祥_成都8 分钟前
前端下午茶!看看炫酷的动画,轻松一下!
前端·动效
lxh011314 分钟前
合并K个升序链表题解
前端·数据结构·链表
小周码代码21 分钟前
js 数字金额转为大写 js 金额转大写
开发语言·前端·javascript·js工具
航Hang*24 分钟前
WEBSTORM前端——第1章:HTML——第2节:列表,表格,下拉菜单,文本框与按钮
前端·html·css3·webstorm
云计算DevOps-韩老师26 分钟前
HTML盒子模型详解
前端·html
不一样的少年_26 分钟前
不仅免费,还开源?这个 AI Mock 神器我必须曝光它
前端·javascript·浏览器
2501_9310480827 分钟前
HTML `<select>` 标签深度解析
前端·html
WZl29 分钟前
在传统的HTML、CSS与JavaScript项目中加入vue
javascript·css·vue.js·html
xcLeigh30 分钟前
AI 绘制图表专栏:用豆包轻松实现 HTML 柱状图、折线图与饼图
前端·人工智能·html·折线图·柱状图·图表·豆包