Lodash源码阅读-dropRightWhile

Lodash 源码阅读-dropRightWhile

概述

dropRightWhile 是一个从数组末尾开始删除元素的函数,但不是简单地删掉固定数量,而是根据条件判断删到什么位置。只要元素满足条件就删,直到遇到第一个不满足条件的元素才停下来。

前置学习

依赖函数

  • baseWhile:内部的条件切片函数,实际干活的是它
  • getIteratee:把各种类型的参数转成标准迭代函数

技术知识

  • 高阶函数:函数可以作为参数传递
  • 谓词函数:返回布尔值的函数,用来判断条件
  • 迭代器简写:Lodash 支持的多种简写形式(对象匹配、属性匹配等)
  • 从右向左处理:从数组末尾开始处理元素的技巧
  • 条件切片:根据元素内容决定切片位置

源码实现

javascript 复制代码
/**
 * Creates a slice of `array` excluding elements dropped from the end.
 * 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': true },
 *   { 'user': 'fred',    'active': false },
 *   { 'user': 'pebbles', 'active': false }
 * ];
 *
 * _.dropRightWhile(users, function(o) { return !o.active; });
 * // => objects for ['barney']
 *
 * // The `_.matches` iteratee shorthand.
 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
 * // => objects for ['barney', 'fred']
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.dropRightWhile(users, ['active', false]);
 * // => objects for ['barney']
 *
 * // The `_.property` iteratee shorthand.
 * _.dropRightWhile(users, 'active');
 * // => objects for ['barney', 'fred', 'pebbles']
 */
function dropRightWhile(array, predicate) {
  return array && array.length
    ? baseWhile(array, getIteratee(predicate, 3), true, true)
    : [];
}

实现思路

dropRightWhile 实现很简单:

  1. 先检查数组是否有效(存在且有长度),无效就返回空数组
  2. 把传入的 predicate(条件函数)通过 getIteratee 转换成标准格式
  3. 调用 baseWhile 函数,参数含义是:
    • 第一个参数:要处理的数组
    • 第二个参数:处理好的条件函数
    • 第三个参数:true 表示"丢弃"模式(而不是"保留"模式)
    • 第四个参数:true 表示从右向左处理(从末尾开始)
  4. baseWhile 会从数组末尾开始,把满足条件的元素都删掉,直到遇到不满足条件的元素

源码解析

空值检查与简洁表达

javascript 复制代码
return array && array.length
  ? baseWhile(array, getIteratee(predicate, 3), true, true)
  : [];

这行代码看着简单,其实包含了很多逻辑:

  • array && array.length 一次性检查了两件事:
    1. 数组是否存在(不是 nullundefined
    2. 数组是否有长度(不是空数组)
  • 如果检查失败,直接返回空数组 []
  • 三元运算符 ? : 让代码非常简洁,避免了 if/else 的冗余

迭代器处理

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

这部分隐藏了很多智能处理:

  • getIteratee 会根据 predicate 的类型返回不同的函数:
    • 如果是函数,原样返回
    • 如果是对象,返回一个检查对象属性是否匹配的函数
    • 如果是数组 [属性, 值],返回一个检查指定属性是否等于指定值的函数
    • 如果是字符串,返回一个获取对象该属性值的函数
  • 参数 3 表示生成的函数会接收三个参数:元素值、索引和原数组

这种设计让 dropRightWhile 支持多种简洁的写法,大大提高了使用灵活性。

baseWhile 的调用

baseWhile(array, getIteratee(predicate, 3), true, true)

这个调用中最关键的是后两个参数:

  • 第三个参数 true 表示 "drop" 模式,即丢弃满足条件的元素
  • 第四个参数 true 表示从右向左处理,这是 dropRightWhile 区别于 dropWhile 的关键

baseWhile 大致的工作流程是:

  1. 确定迭代起点(从右向左则从数组末尾开始)
  2. 不断检查元素是否满足条件
  3. 满足条件就继续检查下一个
  4. 一旦遇到不满足条件的元素,就停止迭代
  5. 根据是 "drop" 还是 "take" 模式以及迭代方向,返回对应的数组切片

总结

dropRightWhile 是一个简单但很实用的函数,它有这些特点:

  1. 条件过滤 - 不是机械地删除固定数量,而是根据元素内容智能决定

  2. 方向性 - 专门处理从右向左(从末尾开始)的场景,与 dropWhile 形成互补

  3. 灵活的条件表达 - 支持多种形式的条件判断,从函数到对象再到属性名

  4. 不可变操作 - 不修改原数组,符合函数式编程理念

常见应用场景包括:删除数据末尾的无效记录、清理文本末尾的特殊字符、取得最近一个特定事件之前的所有记录等。

通过简单的条件表达式,dropRightWhile 让"从末尾删除满足某个条件的元素"这个操作变得优雅而直观,避免了手写循环和复杂判断逻辑。

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