Lodash源码阅读-fill

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 函数的实现流程很清晰:

  1. 首先检查数组是否有效,如果为空就直接返回空数组
  2. 然后检查 start 参数是否是特殊的迭代器调用格式(这是为了兼容 Lodash 的链式调用)
    • 如果是,就重置 start 为 0,end 为数组长度
  3. 最后调用 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 函数虽然简单,但它具有几个重要特点:

  1. 修改原数组 - 它是一个会改变原数组的方法,这一点要特别注意

  2. 灵活的索引 - 支持指定填充的起始和结束位置,还能处理负数索引

  3. 边界处理 - 内部会处理各种边界情况,包括无效输入、越界索引等

这个函数在很多场景下都很有用,比如:

  • 初始化特定大小的数组
  • 重置数组中的一部分元素
  • 创建具有特定模式的数组

使用示例:

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]
相关推荐
缓慢更新41 分钟前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易1 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
风骏时光牛马2 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端
IT_陈寒3 小时前
JavaScript的this坑人实录,这次我真的记下来了
前端·人工智能·后端
开开心心就好4 小时前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
螺丝钉tina5 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
PedroQue995 小时前
0.8.2 新增 backFallback 配置,无 tabbar 页返回无忧
前端·uni-app
淡漠的蓝精灵6 小时前
web.py:一个简单到极致的 Python Web 框架
开发语言·前端·python·其他
开开心心就好6 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
起个名字费劲死了6 小时前
Halcon学习一:骰子识别
前端·python·学习