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]
相关推荐
落霞的思绪1 小时前
CSS复习
前端·css
咖啡の猫3 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲5 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5816 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路6 小时前
GeoTools 读取影像元数据
前端
ssshooter6 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友6 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry7 小时前
Jetpack Compose 中的状态
前端
dae bal8 小时前
关于RSA和AES加密
前端·vue.js
柳杉8 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化