Lodash源码阅读-arrayFilter

Lodash 源码阅读-arrayFilter

功能概述

arrayFilter 是 Lodash 库中的一个内部工具函数,它是 _.filter 方法针对数组类型的特化实现。这个函数的主要作用是遍历数组,并根据提供的断言函数(predicate)过滤出符合条件的元素,返回一个新的数组。与公开的 _.filter 方法不同,arrayFilter 不支持迭代器简写形式,它是一个更加精简和专注的内部实现。

前置学习

依赖关系

arrayFilter 是一个相对独立的函数,它不直接依赖其他 Lodash 函数。但要理解它在 Lodash 中的应用,建议了解以下相关函数:

  • filter :公开的 API,它根据集合类型选择使用 arrayFilterbaseFilter
  • baseFilter:处理非数组集合(如对象)的过滤实现

技术知识

  • JavaScript 中的数组操作:遍历、过滤和创建新数组
  • 断言函数(predicate):返回布尔值的函数,用于测试元素是否符合条件
  • 循环和迭代:使用 while 循环进行迭代操作

源码实现

javascript 复制代码
/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
    length = array == null ? 0 : array.length,
    resIndex = 0,
    result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

实现思路

arrayFilter 函数的实现思路非常直接明了,可以分为以下几个步骤:

  1. 初始化:创建索引变量、结果数组和结果索引
  2. 遍历数组:使用 while 循环遍历原数组的每个元素
  3. 条件判断:对每个元素应用断言函数进行测试
  4. 收集结果:将通过测试的元素添加到结果数组中
  5. 返回结果:返回包含所有通过测试元素的新数组

这种实现方式简洁高效,没有额外的检查和处理逻辑,专注于核心功能的实现。

源码解析

参数解析

javascript 复制代码
function arrayFilter(array, predicate) {

函数接收两个参数:

  • array:要遍历的数组,可以是 null 或 undefined
  • predicate:每次迭代调用的断言函数,它接收三个参数:当前元素值、索引和原数组

初始化变量

javascript 复制代码
var index = -1,
  length = array == null ? 0 : array.length,
  resIndex = 0,
  result = [];

这段代码初始化了四个变量:

  • index:遍历索引,初始值为 -1,这样在第一次循环时 ++index 会使其变为 0
  • length:数组长度,如果数组为 null 或 undefined,则长度为 0
  • resIndex:结果数组的当前索引,用于追踪结果数组的填充位置
  • result:结果数组,初始为空数组

遍历和过滤

javascript 复制代码
while (++index < length) {
  var value = array[index];
  if (predicate(value, index, array)) {
    result[resIndex++] = value;
  }
}

这段代码是函数的核心部分:

  1. 使用 while 循环,从 0 到 length-1 遍历数组
  2. 获取当前索引对应的元素值
  3. 调用断言函数 predicate(value, index, array) 测试当前元素
  4. 如果断言函数返回真值(truthy),则将当前元素添加到结果数组中,并增加结果索引

这种实现方式确保了只有通过断言测试的元素才会被添加到结果数组中。

返回结果

javascript 复制代码
return result;

最后,函数返回包含所有通过测试元素的新数组。

与原生方法的比较

arrayFilter 与 JavaScript 原生的 Array.prototype.filter 方法有一些相似之处和区别:

javascript 复制代码
// 原生 Array.prototype.filter
Array.prototype.filter = function (callback, thisArg) {
  if (this == null) {
    throw new TypeError("this is null or not defined");
  }

  var O = Object(this);
  var len = O.length >>> 0;
  var A = new Array(0);
  var k = 0;
  var to = 0;

  while (k < len) {
    if (k in O) {
      var kValue = O[k];
      if (callback.call(thisArg, kValue, k, O)) {
        A[to++] = kValue;
      }
    }
    k++;
  }

  return A;
};

相似之处:

  1. 都使用循环遍历数组元素
  2. 都调用回调函数测试每个元素
  3. 都创建并返回一个新数组

区别:

  1. 错误处理

    • 原生方法会对 null 和 undefined 抛出 TypeError
    • arrayFilter 将 null 和 undefined 视为空数组
  2. 稀疏数组处理

    • 原生方法会跳过数组中的空洞(稀疏数组中未设置的元素)
    • arrayFilter 会处理所有索引,包括未设置的元素(将其视为 undefined)
  3. this 绑定

    • 原生方法支持通过第二个参数设置回调函数的 this 值
    • arrayFilter 不支持设置 this 值
  4. 类型强制

    • 原生方法对输入进行更严格的类型检查和强制转换
    • arrayFilter 假设输入已经是合适的类型

总结

arrayFilter 是 Lodash 中一个简单但强大的内部工具函数,它提供了一种高效的方式来过滤数组元素。虽然它是一个内部函数,但通过 _.filter 方法,它的功能被暴露给了库的使用者。

相关推荐
利刃之灵2 分钟前
03-HTML常见元素
前端·html
kidding7238 分钟前
gitee新的仓库,Vscode创建新的分支详细步骤
前端·gitee·在仓库创建新的分支
听风吹等浪起11 分钟前
基于html实现的课题随机点名
前端·html
leluckys17 分钟前
flutter 专题 六十三 Flutter入门与实战作者:xiangzhihong8Fluter 应用调试
前端·javascript·flutter
kidding72331 分钟前
微信小程序怎么分包步骤(包括怎么主包跳转到分包)
前端·微信小程序·前端开发·分包·wx.navigateto·subpackages
微学AI1 小时前
详细介绍:MCP(大模型上下文协议)的架构与组件,以及MCP的开发实践
前端·人工智能·深度学习·架构·llm·mcp
liangshanbo12151 小时前
CSS 包含块
前端·css
Mitchell_C1 小时前
语义化 HTML (Semantic HTML)
前端·html
倒霉男孩1 小时前
CSS文本属性
前端·css
shoa_top1 小时前
JavaScript 数组方法总结
javascript