Lodash 源码阅读-dropRight
概述
dropRight
函数用来从数组的末尾删除指定数量的元素,并返回剩下的部分。它和 drop
是一对,一个削头,一个削尾。不会修改原数组,会返回一个新数组。
前置学习
依赖函数
- baseSlice:内部切片函数,实际干活的是它
- toInteger:把各种类型的值转成整数
技术知识
- 数组切片:从数组中提取部分元素形成新数组
- 参数默认值:参数未提供时使用默认值
- 防御性编程:处理各种边界情况和异常输入
- Guard 参数:在高阶函数中防止额外参数误用
- 索引计算:根据数组长度和要删除的元素计算切片范围
源码实现
javascript
/**
* Creates a slice of `array` with `n` elements dropped from the end.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=1] The number of elements to drop.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.dropRight([1, 2, 3]);
* // => [1, 2]
*
* _.dropRight([1, 2, 3], 2);
* // => [1]
*
* _.dropRight([1, 2, 3], 5);
* // => []
*
* _.dropRight([1, 2, 3], 0);
* // => [1, 2, 3]
*/
function dropRight(array, n, guard) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
n = guard || n === undefined ? 1 : toInteger(n);
n = length - n;
return baseSlice(array, 0, n < 0 ? 0 : n);
}
实现思路
dropRight
函数的实现很直观:
- 先检查数组是不是空的,是就直接返回空数组
- 确定要删除的元素数量
n
,默认是 1 - 计算新数组的结束位置:
length - n
- 用
baseSlice
从 0 切到这个位置 - 如果计算出的位置是负数(删除的比数组长度还多),就切到 0(返回空数组)
源码解析
空值和长度检查
javascript
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
这两行代码是防御性编程的体现:
- 先判断
array
是不是null
或undefined
(用==
一次检查两种情况) - 如果是,就把长度设为 0,避免报错
- 然后检查长度是否为 0,是则直接返回空数组,避免后续无谓操作
参数处理
javascript
n = guard || n === undefined ? 1 : toInteger(n);
这行处理删除元素的数量:
- 如果有
guard
参数(比如在_.map
里用dropRight
当迭代器),或者没传n
,就用默认值 1 - 否则用
toInteger
把n
转成整数,确保计算准确
看起来复杂,其实就是在设置默认值,不过同时还考虑了函数用作高阶函数参数的情况。
计算切片范围
javascript
n = length - n;
这行很关键,用来计算新数组应该到哪里结束:
- 用数组长度减去要删除的元素数量
- 例如:数组
[1, 2, 3]
长度为 3,要删除末尾 1 个元素,那么切片应该到3 - 1 = 2
的位置,即保留索引 0 和 1 的元素
执行切片
javascript
return baseSlice(array, 0, n < 0 ? 0 : n);
最后调用 baseSlice
完成实际切片操作:
- 从索引 0 开始(保留数组头部)
- 切到刚才计算的
n
位置 - 如果
n
小于 0(说明删除的元素比数组长度还多),就切到 0,也就是返回空数组 - 例如:数组
[1, 2, 3]
删除末尾 5 个元素,计算出n = 3 - 5 = -2
,小于 0,所以切到 0,返回[]
总结
dropRight
是一个简单但实用的数组处理函数,特点如下:
-
不可变操作 - 不修改原数组,返回新数组,符合函数式编程理念
-
参数灵活 - 支持默认值和各种类型输入,很人性化
-
健壮性强 - 能处理各种边界情况,不会轻易报错
-
与其他函数互补 - 与
drop
形成一套头尾操作组合
这样的设计让我们在处理数组末尾元素时不必手动计算索引,直接说"我要去掉末尾几个元素"就行了,既直观又不易出错。
常见应用场景包括:移除数组末尾元素、处理时间序列数据时忽略最近的不稳定数据点、获取路径目录、创建不包含尾部元素的数组副本等。