Lodash 源码阅读-remove
概述
remove
是 Lodash 中的一个数组方法,用于移除数组中满足指定条件的所有元素,并返回这些被移除的元素组成的新数组。与过滤方法不同的是,remove
会直接修改原数组,而不是创建一个新数组。
前置学习
依赖函数
- getIteratee:获取迭代器函数,将传入的条件转换为标准函数
- basePullAt:从数组中移除指定索引位置的元素的基础实现
技术知识
- 数组操作:数组元素的遍历和删除
- 谓词函数:用于测试数组元素是否满足条件的函数
- 副作用操作:直接修改原始数据的操作
- 迭代器模式:使用函数对集合进行操作的设计模式
源码实现
javascript
function remove(array, predicate) {
var result = [];
if (!(array && array.length)) {
return result;
}
var index = -1,
indexes = [],
length = array.length;
predicate = getIteratee(predicate, 3);
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result.push(value);
indexes.push(index);
}
}
basePullAt(array, indexes);
return result;
}
实现思路
remove
函数的实现思路非常直观:
- 首先创建一个空数组
result
用于存储将被移除的元素 - 如果输入数组不存在或长度为 0,直接返回空结果数组
- 将传入的
predicate
参数转换为标准的迭代器函数,确保它接受三个参数(值、索引、数组) - 遍历数组,对每个元素应用谓词函数
- 如果元素满足条件(谓词函数返回真值),则:
- 将元素添加到结果数组中
- 记录元素的索引位置
- 遍历完成后,使用
basePullAt
函数批量移除所有记录的索引位置的元素 - 返回包含所有被移除元素的结果数组
这种实现既高效又优雅,通过先收集所有需要删除的元素和索引,然后一次性执行删除操作,避免了在遍历过程中直接修改数组可能导致的索引错位问题。
源码解析
初始化与边界检查
javascript
var result = [];
if (!(array && array.length)) {
return result;
}
函数首先创建一个空数组 result
用于存储将被移除的元素。然后检查输入数组是否存在且长度大于 0,如果不满足条件则提前返回空结果数组。这是一个常见的优化技巧,避免对空数组进行不必要的处理。
变量初始化
javascript
var index = -1,
indexes = [],
length = array.length;
这里初始化了三个变量:
index
:用于遍历数组的索引,初始为 -1(因为循环开始时会先自增)indexes
:用于记录需要删除的元素的索引位置length
:缓存数组长度,避免在循环中重复获取
转换谓词函数
javascript
predicate = getIteratee(predicate, 3);
使用 getIteratee
函数将传入的 predicate
转换为标准的迭代器函数。参数 3
表示该函数应该接受三个参数:值、索引、数组。这允许用户以多种方式传入条件,如函数、对象、数组或字符串,getIteratee
会将它们统一转换为适当的函数。
遍历数组并收集满足条件的元素
javascript
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result.push(value);
indexes.push(index);
}
}
通过 while
循环遍历数组的每个元素,对每个元素:
- 使用谓词函数测试元素是否满足条件
- 如果满足条件,将元素添加到结果数组,并记录其索引位置
这个过程不会修改原数组,只是在收集需要移除的元素和索引。
批量移除元素并返回结果
javascript
basePullAt(array, indexes);
return result;
最后,调用 basePullAt
函数,根据收集的索引批量移除原数组中的元素。这个操作会直接修改原数组。然后返回之前收集的所有被移除元素组成的数组。
总结
remove
函数是 Lodash 中一个实用的数组操作工具,它巧妙地解决了"查找并移除满足条件的所有元素"这一常见需求。其特点包括:
- 原地修改:直接修改原数组,不需要额外的赋值操作
- 返回移除的元素:同时返回被移除的元素,便于进一步处理
- 批量操作:先收集所有要移除的索引,然后一次性删除,避免了遍历中修改数组的问题
- 灵活的条件指定:支持多种形式的条件指定,如函数、对象、数组或字符串
这个函数在需要同时获取被移除元素并更新原数组的场景中特别有用,它提供了比原生 JavaScript 数组方法更强大和便捷的功能。与 filter
方法相比,remove
方法直接修改原数组,适用于不需要保留原数组的场景,可以节省内存并简化代码。