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]
相关推荐
AI_零食34 分钟前
番茄钟鸿蒙PC Electron框架完成:状态机、定时器管理与专注力工具设计
前端·javascript·华为·electron·开源·鸿蒙·鸿蒙系统
提子拌饭13335 分钟前
逛三园游戏——基于鸿蒙PC Electron框架实现
前端·javascript·游戏·华为·electron·鸿蒙
llz_11237 分钟前
web-第三次课后作业
前端·后端·web
遗憾随她而去.1 小时前
Web地图全体系深度梳理:引擎、数据源、图层、投影核心知识
前端
爱因斯坦乐1 小时前
Vue项目整合
前端·javascript·vue.js
FlyWIHTSKY1 小时前
TS、TSX、JS、JSX 文件扩展名详解
开发语言·javascript·ecmascript
无风听海1 小时前
IndexedDB 深度指南 浏览器中的事务型对象数据库
前端·数据库
ct9782 小时前
组件间的通信
前端·javascript·vue.js
左手吻左脸。3 小时前
Vue 全栈面试题大全(2026 最新版最详细)
前端·javascript·vue.js
Aphasia3113 小时前
手写KeepAlive组件
前端·react.js·面试