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

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

相关推荐
To_OC1 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC1 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic1 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy1 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志2 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble3 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长3 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯4 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜4 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司5 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能