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 让"从末尾删除满足某个条件的元素"这个操作变得优雅而直观,避免了手写循环和复杂判断逻辑。

相关推荐
magic 2451 小时前
Spring 命名空间注入:p、c 与 .util 的深度解析
java·前端·spring
钢铁男儿2 小时前
Python基本语法(函数partial)
前端·javascript·python
风清云淡_A2 小时前
【angular19】入门基础教程(三):关于angular里面的响应式数据入门使用
前端·angular.js
green_pine_2 小时前
Vue3学习笔记2——路由守卫
前端·vue.js·笔记·学习
空中湖2 小时前
纯前端专业PDF在线浏览器查看器工具
前端·pdf
七灵微2 小时前
ES6入门---第二单元 模块二:关于数组新增
前端·javascript·es6
GUIQU.2 小时前
【Vue】性能优化与调试技巧
前端·vue.js·性能优化
娃哈哈哈哈呀3 小时前
组件通信-mitt
前端·javascript·vue.js
wuhen_n3 小时前
鼠标悬浮特效:常见6种背景类悬浮特效
前端·css·css3·html5
娃哈哈哈哈呀3 小时前
组件通信-v-model
java·服务器·前端