Lodash 源码阅读-fill
概述
fill 函数用来用指定的值填充数组,可以指定起始位置和结束位置。这个函数会修改原数组,而不是创建新数组。
前置学习
依赖函数
- baseFill:实际执行填充操作的函数
 - toInteger:把起始位置和结束位置转成整数
 - isIterateeCall:检测参数是否是迭代器调用格式
 
技术知识
- 数组操作:基本的数组修改操作
 - 参数默认值:处理可选参数的默认值
 - 边界处理:处理负索引和越界情况
 
源码实现
            
            
              javascript
              
              
            
          
          function fill(array, value, start, end) {
  var length = array == null ? 0 : array.length;
  if (!length) {
    return [];
  }
  if (
    start &&
    typeof start != "number" &&
    isIterateeCall(array, value, start)
  ) {
    start = 0;
    end = length;
  }
  return baseFill(array, value, start, end);
}
        实现思路
fill 函数的实现流程很清晰:
- 首先检查数组是否有效,如果为空就直接返回空数组
 - 然后检查 
start参数是否是特殊的迭代器调用格式(这是为了兼容 Lodash 的链式调用)- 如果是,就重置 
start为 0,end为数组长度 
 - 如果是,就重置 
 - 最后调用 
baseFill函数执行实际的填充操作,它会:- 处理起始位置和结束位置的边界情况
 - 在指定范围内用给定值替换数组元素
 - 返回修改后的数组
 
 
源码解析
空值处理
            
            
              javascript
              
              
            
          
          var length = array == null ? 0 : array.length;
if (!length) {
  return [];
}
        这段代码检查数组是否为 null 或 undefined,或者是否为空数组:
- 如果数组为 
null或undefined,则length为 0 - 如果数组长度为 0,直接返回空数组
 - 对无效输入的防御性编程,确保函数行为可预测
 
迭代器调用检查
            
            
              javascript
              
              
            
          
          if (start && typeof start != "number" && isIterateeCall(array, value, start)) {
  start = 0;
  end = length;
}
        这段代码处理一种特殊情况,当 start 不是数字且满足 isIterateeCall 条件时:
- 重置 
start为 0,end为数组长度 - 这种情况通常出现在链式调用或某些 Lodash 的内部使用场景
 isIterateeCall函数检查start是否是一个对象,且满足start[0] === value这种模式
调用 baseFill
            
            
              javascript
              
              
            
          
          return baseFill(array, value, start, end);
        最后调用内部的 baseFill 函数,它会:
- 将 
start和end转换为有效的整数索引 - 处理负数索引(从数组末尾计算位置)
 - 确保索引在有效范围内
 - 执行实际的数组填充操作
 
baseFill 的核心实现是一个简单的循环:
            
            
              javascript
              
              
            
          
          while (start < end) {
  array[start++] = value;
}
        这个循环从 start 到 end(不包括 end)填充数组的每个位置。
总结
fill 函数虽然简单,但它具有几个重要特点:
- 
修改原数组 - 它是一个会改变原数组的方法,这一点要特别注意
 - 
灵活的索引 - 支持指定填充的起始和结束位置,还能处理负数索引
 - 
边界处理 - 内部会处理各种边界情况,包括无效输入、越界索引等
 
这个函数在很多场景下都很有用,比如:
- 初始化特定大小的数组
 - 重置数组中的一部分元素
 - 创建具有特定模式的数组
 
使用示例:
            
            
              javascript
              
              
            
          
          // 用 'a' 填充整个数组
_.fill([1, 2, 3], "a");
// => ['a', 'a', 'a']
// 创建并填充数组
_.fill(Array(3), 2);
// => [2, 2, 2]
// 只填充部分数组
_.fill([4, 6, 8, 10], "*", 1, 3);
// => [4, '*', '*', 10]