Lodash 源码阅读-baseFill
概述
baseFill
是 Lodash 内部用来实现 fill
方法的核心函数,它能够用指定值填充数组中的元素,支持指定起始和结束位置。这个函数处理了各种边界情况,并且保证了填充操作的准确性。
前置学习
依赖函数
- toInteger:将值转换为整数,处理起始位置和结束位置参数
- toLength:将值转换为有效的数组长度,确保结束位置在有效范围内
技术知识
- 数组操作:数组元素的赋值和修改
- 循环控制:使用 while 循环进行数组元素填充
- 参数处理:处理负数索引、起始位置大于结束位置等边界情况
源码实现
javascript
function baseFill(array, value, start, end) {
var length = array.length;
start = toInteger(start);
if (start < 0) {
start = -start > length ? 0 : length + start;
}
end = end === undefined || end > length ? length : toInteger(end);
if (end < 0) {
end += length;
}
end = start > end ? 0 : toLength(end);
while (start < end) {
array[start++] = value;
}
return array;
}
实现思路
baseFill
的实现逻辑非常直观但很完善:
- 首先获取数组的长度
- 处理起始位置参数
start
:- 转换为整数
- 如果为负数,将其转换为相对于数组末尾的位置
- 如果转换后仍小于 0,则设为 0
- 处理结束位置参数
end
:- 如果未定义或大于数组长度,则设为数组长度
- 否则转换为整数
- 如果为负数,将其转换为相对于数组末尾的位置
- 确保结束位置有效:
- 如果起始位置大于结束位置,则结束位置设为 0
- 否则使用
toLength
确保结束位置在有效范围内
- 使用循环将指定值填充到数组的指定位置
- 返回修改后的数组
源码解析
初始化和参数处理
javascript
var length = array.length;
start = toInteger(start);
if (start < 0) {
start = -start > length ? 0 : length + start;
}
这部分代码首先获取数组长度,然后处理起始位置 start
:
- 使用
toInteger
将其转换为整数 - 如果是负数,则计算相对于数组末尾的位置
- 如果负数的绝对值大于数组长度,就设为 0
例如:
javascript
// 数组长度为5
start = -2 => 5 + (-2) = 3 // 表示从倒数第二个元素开始
start = -10 => 0 // 因为|-10| > 5,所以设为0
结束位置处理
javascript
end = end === undefined || end > length ? length : toInteger(end);
if (end < 0) {
end += length;
}
end = start > end ? 0 : toLength(end);
这部分代码处理结束位置 end
:
- 如果未定义或大于数组长度,设为数组长度
- 否则转换为整数
- 如果是负数,计算相对于数组末尾的位置
- 最后,如果起始位置大于结束位置,则结束位置设为 0;否则使用
toLength
确保结束位置是一个有效的数组长度值
例如:
javascript
// 数组长度为5,start为1
end = undefined => 5 // 未定义,设为数组长度
end = -2 => 5 + (-2) = 3 // 表示倒数第二个元素的位置
end = 10 => 5 // 超出数组长度,设为数组长度
填充操作
javascript
while (start < end) {
array[start++] = value;
}
return array;
这是函数的核心填充逻辑:
- 使用
while
循环从起始位置到结束位置(不包括结束位置) - 在每个位置设置指定的值
- 使用
start++
同时赋值和递增索引 - 最后返回修改后的数组
总结
baseFill
函数看似简单,但它展示了几个重要的编程原则:
-
健壮性:通过仔细处理边界情况(负索引、超出范围的值等)确保函数在各种输入下都能正常工作
-
参数规范化 :使用
toInteger
和toLength
将输入标准化,增强函数的适应性 -
副作用明确:函数直接修改并返回原数组,使得副作用明确且可预测
baseFill
是一个很好的例子,展示了如何处理数组边界和索引转换,这在很多数组操作中都是常见且重要的技术。