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 [];
}

这段代码检查数组是否为 nullundefined,或者是否为空数组:

  • 如果数组为 nullundefined,则 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 函数,它会:

  • startend 转换为有效的整数索引
  • 处理负数索引(从数组末尾计算位置)
  • 确保索引在有效范围内
  • 执行实际的数组填充操作

baseFill 的核心实现是一个简单的循环:

javascript 复制代码
while (start < end) {
  array[start++] = value;
}

这个循环从 startend(不包括 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]
相关推荐
kyriewen12 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_233313 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
山河木马14 小时前
矩阵专题3-怎么创建投影矩阵(uProjectionMatrix)
javascript·webgl·计算机图形学
天蓝色的鱼鱼15 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
泯泷16 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花16 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷16 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
团团崽_七分甜16 小时前
Spring Boot 核心知识点总结
前端
lichenyang45316 小时前
从一个按钮开始,理解 ASCF 框架到底在做什么
前端