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

相关推荐
zwjapple3 小时前
docker-compose一键部署全栈项目。springboot后端,react前端
前端·spring boot·docker
像风一样自由20205 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem6 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊6 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术6 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing6 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止6 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall6 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴7 小时前
简单入门Python装饰器
前端·python
袁煦丞7 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作