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 方法,它的功能被暴露给了库的使用者。

相关推荐
xjt_09012 分钟前
浅析Web存储系统
前端
foxhuli22940 分钟前
禁止ifrmare标签上的文件,实现自动下载功能,并且隐藏工具栏
前端
青皮桔1 小时前
CSS实现百分比水柱图
前端·css
失落的多巴胺1 小时前
使用deepseek制作“喝什么奶茶”随机抽签小网页
javascript·css·css3·html5
DataGear1 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
影子信息1 小时前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月1 小时前
1.vue权衡的艺术
前端·vue.js·开源
样子20181 小时前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿1 小时前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
翻滚吧键盘1 小时前
vue文本插值
javascript·vue.js·ecmascript