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

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

相关推荐
AAA阿giao1 分钟前
HTML/CSS/JS 页面渲染机制:揭秘浏览器如何将平凡代码点化为视觉魔法
前端·css·html
lichenyang4536 分钟前
从零到一:编写一个简单的 Umi 插件并发布到 npm
前端·react.js·前端框架
一颗宁檬不酸8 分钟前
ajxa实例操作
前端·ajax·api
文心快码BaiduComate9 分钟前
CCF程序员大会码力全开:AI加速营,10w奖金等你拿!
前端·后端·程序员
前端西瓜哥18 分钟前
Figma 协同编辑是如何做用户状态同步的?
前端
OpenTiny社区20 分钟前
不止按钮和表格!TinyVue 偷偷上线 Space 组件,直接搞定「弹性+间距」布局
前端·vue.js·github
FogLetter27 分钟前
Vue 全家桶深度探索:从语法精要到项目实战
前端·vue.js
木易士心28 分钟前
Vue 3 Props 响应式深度解析:从原理到最佳实践
前端
FogLetter28 分钟前
从零实现一个低代码编辑器:揭秘可视化搭建的核心原理
前端·react.js·低代码
花归去30 分钟前
vue甘特图
前端·javascript·vue.js