Lodash源码阅读-takeRightWhile

Lodash 源码阅读-takeRightWhile

概述

takeRightWhile 函数用于从数组末尾提取元素,直到遇到第一个不满足条件的元素为止。它不是简单地提取固定数量元素,而是根据条件动态决定提取哪些元素,特别适合从数据末尾获取满足特定条件的连续元素。

前置学习

依赖函数

  • baseWhile:提供条件数组切片的内部函数
  • getIteratee:转换各种形式谓词为标准函数的工具

技术知识

  • 高阶函数:接收函数作为参数的编程方式
  • 谓词函数:返回布尔值的判断函数
  • 迭代器简写:Lodash 中的简写表达式
  • 数组切片:创建数组子集的操作
  • 从右向左迭代:从数组末尾开始处理元素

源码实现

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

实现思路

takeRightWhile 实现非常直接:先检查数组是否有效,然后调用 baseWhile 函数处理具体逻辑。传给 baseWhile 的四个参数分别是:原数组、转换后的谓词函数、操作模式(false 表示"提取")和方向标识(true 表示"从右向左")。这个函数从数组末尾开始,连续提取满足条件的元素,直到遇到第一个不满足条件的元素。

源码解析

参数检查

javascript 复制代码
array && array.length ? ... : []

这行代码处理边界情况:

  • 如果数组为 nullundefined 或空数组,直接返回空数组
  • 用短路表达式简洁地处理无效输入

例如:

javascript 复制代码
_.takeRightWhile(null, (x) => x > 0); // => []
_.takeRightWhile([], (x) => x > 0); // => []

迭代器处理

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

这部分负责将各种形式的谓词转换为标准函数:

  • 数字 3 表示迭代函数接收三个参数:值、索引、原数组
  • 支持四种谓词形式:
    • 函数形式:如 x => !x.active
    • 对象匹配形式:如 {user: 'pebbles', active: false}
    • 属性值匹配形式:如 ['active', false]
    • 属性访问形式:如 'active'(检查属性是否为真值)

这种灵活性大大提高了函数的易用性:

javascript 复制代码
// 四种等效写法
_.takeRightWhile(users, (user) => !user.active);
_.takeRightWhile(users, { active: false });
_.takeRightWhile(users, ["active", false]);
_.takeRightWhile(users, "active"); // 提取属性为真的元素

baseWhile 调用

javascript 复制代码
baseWhile(array, getIteratee(predicate, 3), false, true);

这是函数核心:

  • 第一个参数是输入数组
  • 第二个参数是转换后的迭代函数
  • 第三个参数 false 指定为"take"模式(保留满足条件的元素)
  • 第四个参数 true 指定从右向左处理(从末尾开始)

baseWhile 的工作流程:

  1. 从数组末尾开始向前迭代
  2. 对每个元素应用谓词函数
  3. 只要谓词返回 true,就将元素加入结果
  4. 一遇到谓词返回 false 的元素,立即停止

例如对数组 [1, 2, 3, 4, 5] 和条件 x => x > 3

  • 从末尾元素 5 开始:满足条件,保留
  • 元素 4:满足条件,保留
  • 元素 3:不满足条件,停止
  • 结果是 [4, 5]

注意结果数组中的元素保持原数组的顺序,不会被反转。

总结

takeRightWhile 函数是 Lodash 中处理数组的实用工具,它体现了以下设计原则:

  1. 方向性处理:支持从右向左(从末尾开始)处理数组
  2. 声明式编程:用简洁的方式表达"取出什么"而非"如何取出"
  3. 功能对称性 :与 takeWhile 形成对称操作,一个从头处理,一个从尾处理
  4. 不可变性:创建新数组而非修改原数组,避免副作用

这个函数在处理时间序列数据、日志文件分析、状态追踪等场景下特别有用,让开发者能用简洁代码提取数组末尾满足条件的连续元素。

相关推荐
mldong2 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排2 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60613 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角4 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!4 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰4 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi6 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马7 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu7 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss