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]
相关推荐
QTX187305 分钟前
使用 Axios 进行 API 请求与接口封装
javascript·vue.js·node.js
9ilk14 分钟前
【前端基础】--- HTML
前端·html
Lafar16 分钟前
Dart单线程怎么保证UI运行流畅
前端·面试
不和乔治玩的佩奇22 分钟前
【 设计模式】常见前端设计模式
前端
bloxed28 分钟前
vue+vite 减缓首屏加载压力和性能优化
前端·vue.js·性能优化
打野赵怀真40 分钟前
React Hooks 的优势和使用场景
前端·javascript
HaushoLin44 分钟前
ERR_PNPM_DLX_NO_BIN No binaries found in tailwindcss
前端·vue.js·css3·html5
Lafar1 小时前
Widget 树和 Element 树和RenderObject树是一一 对应的吗
前端
似水流年QC1 小时前
什么是Lodash
javascript·lodash
小桥风满袖1 小时前
炸裂,前端神级动效库合集
前端·css