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

相关推荐
海晨忆6 分钟前
【Vue】v-if和v-show的区别
前端·javascript·vue.js·v-show·v-if
JiangJiang30 分钟前
🚀 Vue人看React useRef:它不只是替代 ref
javascript·react.js·面试
1024小神35 分钟前
在GitHub action中使用添加项目中配置文件的值为环境变量
前端·javascript
龙骑utr39 分钟前
qiankun微应用动态设置静态资源访问路径
javascript
Jasmin Tin Wei40 分钟前
css易混淆的知识点
开发语言·javascript·ecmascript
齐尹秦43 分钟前
CSS 列表样式学习笔记
前端
wsz77771 小时前
js封装系列(一)
javascript
Mnxj1 小时前
渐变边框设计
前端
用户7678797737321 小时前
由Umi升级到Next方案
前端·next.js
快乐的小前端1 小时前
TypeScript基础一
前端