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

相关推荐
掘金安东尼29 分钟前
上周前端发生哪些新鲜事儿? #407
前端·面试·github
小谭鸡米花38 分钟前
ECharts各类炫酷图表/3D柱形图
前端·javascript·echarts·大屏端
郝晨妤43 分钟前
【鸿蒙5.0】向用户申请麦克风授权
linux·服务器·前端·华为·harmonyos·鸿蒙
神秘代码行者1 小时前
使用 contenteditable 属性实现网页内容可编辑化
前端·html5
小鱼人爱编程1 小时前
Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式
java·前端·后端
郝晨妤1 小时前
【鸿蒙5.0】鸿蒙登录界面 web嵌入(隐私页面加载)
前端·华为·harmonyos
小鱼人爱编程1 小时前
当上小组长的第3天,我裁掉了2年老员工
前端·后端·面试
晓得迷路了1 小时前
栗子前端技术周刊第 74 期 - 2025 Vue.js 现状报告、Element Plus X、Material UI v7...
前端·javascript·vue.js
知识分享小能手1 小时前
CSS3学习教程,从入门到精通, CSS3 变形效果(2D 和 3D)的详细语法知识点及案例代码(22)
前端·javascript·css·学习·3d·css3·html5
花之亡灵1 小时前
.net 6 + vue3中使用SignaIR实现双向通信功能
前端·javascript·笔记·websocket·.net·信息与通信