Lodash源码阅读-takeWhile

Lodash 源码阅读-takeWhile

概述

takeWhile 函数从数组开头开始取元素,但不是简单地取固定数量,而是根据条件判断取到哪里停止。只要元素满足条件就继续取,一旦遇到第一个不满足条件的元素就立即停下来。简单说就是"一路取,遇到不符合的就停"。

前置学习

依赖函数

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

技术知识

  • 高阶函数:函数可以作为参数传递
  • 谓词函数:返回布尔值的函数,用来判断条件
  • 迭代器简写:Lodash 支持的多种条件表达方式
  • 短路处理:一旦条件不满足就立即停止处理
  • 函数柯里化:预处理函数参数,提高复用性

源码实现

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

实现思路

takeWhile 的实现非常直观:

  1. 先检查数组是否有效(存在且有长度),无效就返回空数组
  2. 把传入的 predicate(条件函数)通过 getIteratee 转换成标准格式
  3. 调用 baseWhile 函数,不传第三个参数(默认是 false),表示这是"提取"模式而不是"丢弃"模式
  4. baseWhile 会从数组开头开始,把满足条件的元素都收集起来,直到遇到不满足条件的元素

源码解析

空值检查与简洁表达

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

这一行代码看起来很简单,但做了很多事情:

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

迭代器处理

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

这部分代码非常智能,能处理多种形式的条件:

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

baseWhile 的调用

由于 baseWhile 没有传第三个和第四个参数,它们默认都是 false,这意味着:

  • 第三个参数 false 表示 "take" 模式,即保留满足条件的元素(而不是丢弃)
  • 第四个参数 false 表示从左向右处理(从开头开始)

baseWhile 的工作流程大致是:

  1. 从数组开头开始遍历
  2. 对每个元素调用条件函数
  3. 如果返回 true,就把这个元素加入结果
  4. 一旦返回 false,立即停止并返回已收集的元素

总结

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

  1. 条件截取 - 不是简单取固定数量,而是根据元素内容智能决定

  2. 短路机制 - 一旦遇到不符合条件的元素立即停止,不会遍历整个数组

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

  4. 函数式风格 - 不修改原数组,返回新数组,避免副作用

这个函数在很多场景下都很有用,比如:

  • 提取文件头部的元数据
  • 获取连续有效的用户输入
  • 截取满足质量要求的数据序列

通过简单的条件表达式,takeWhile 让"获取满足条件的连续元素"这个操作变得优雅而直观,避免了手写循环和复杂判断逻辑。

相关推荐
小兵张健4 小时前
价值1000的 AI 工作流:Codex 通用前端协作模式
前端·aigc·ai编程
sunny_4 小时前
面试踩大坑!同一段 Node.js 代码,CJS 和 ESM 的执行顺序居然是反的?!99% 的人都答错了
前端·面试·node.js
拉不动的猪5 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
冬奇Lab5 小时前
OpenClaw 深度解析(四):插件 SDK 与扩展开发机制
人工智能·开源·源码阅读
ayqy贾杰6 小时前
Agent First Engineering
前端·vue.js·面试
IT_陈寒6 小时前
SpringBoot实战:5个让你的API性能翻倍的隐藏技巧
前端·人工智能·后端
iceiceiceice7 小时前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
大金乄7 小时前
封装一个vue2的elementUI 表格组件(包含表格编辑以及多级表头)
前端·javascript
葡萄城技术团队8 小时前
【性能优化篇】面对万行数据也不卡顿?揭秘协同服务器的“片段机制 (Fragments)”
前端
程序员阿峰8 小时前
2026前端必备:TensorFlow.js,浏览器里的AI引擎,不写Python也能玩转智能
前端