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

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

相关推荐
袁煦丞21 分钟前
8.12实验室 指尖魔法变出艺术感 Excalidraw:cpolar内网穿透实验室第495个成功挑战
前端·程序员·远程工作
烛阴26 分钟前
Dot
前端·webgl
Gene_202227 分钟前
使用行为树控制机器人(三) ——通用端口
前端·机器人
excel1 小时前
JavaScript 中的二进制数据:ArrayBuffer 与 SharedArrayBuffer 全面解析
前端
ZXT2 小时前
代码规范与提交
前端
柑橘乌云_2 小时前
vue中如何在父组件监听子组件的生命周期
前端·javascript·vue.js
北海天空3 小时前
react-scripts的webpack.config.js配置解析
前端
LilyCoder3 小时前
HTML5中华美食网站源码
前端·html·html5
拾光拾趣录3 小时前
模块联邦(Module Federation)微前端方案
前端·webpack
江湖人称小鱼哥3 小时前
react接口防抖处理
前端·javascript·react.js