You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript的splice()在两种数组创建方式下表现不同?

核心原因:稀疏数组与密集数组的行为差异

你的猜测完全正确,两段代码的差异本质是**稀疏数组(sparse array)**和密集数组的区别导致的。

先明确两段代码的实际输出

  • 第一段(new Array(3))运行结果:undefined
  • 第二段(字面量创建)运行结果:3

详细解析差异根源

1. 两种数组创建方式的本质区别

  • const arr = [1, 2, 3]:创建的是密集数组,索引0、1、2都有明确的元素值,数组长度为3,不存在空槽。
  • const arr = new Array(3):创建的是稀疏数组,数组长度设为3,但索引0、1、2的位置是空槽(empty slot)——注意,空槽不是undefined,而是数组中根本不存在的索引位置。

2. 操作后的数组结构变化

第一段代码的完整流程:
  1. 初始状态:new Array(3) → 结构为 [empty × 3],长度3,无实际元素。
  2. 三次push后:数组长度变为6,结构是 [empty × 3, 1, 2, 3](索引0、1、2是空槽,3=1,4=2,5=3)。
  3. 执行arr.splice(0, 2):删除索引0、1的两个空槽,剩余数组结构变为 [empty × 1, 1, 2, 3](原索引2的空槽留在索引0,原索引3-5的元素前移到索引1-3)。
  4. 访问arr[0]时,因为该位置是空槽,返回undefined。
第二段代码的完整流程:
  1. 初始状态:[1, 2, 3] → 密集数组,索引0=1,1=2,2=3,长度3。
  2. 执行arr.splice(0, 2):删除索引0、1的元素(1和2),剩余元素3前移到索引0,数组变为[3]。
  3. 访问arr[0]直接返回3。

3. 关于“索引不从0开始”的问题

你遇到的“索引看似从splice位置开始”是稀疏数组的特性导致的:
稀疏数组的空槽不会被forEach、map等常规遍历方法处理,当你打印数组或用工具查看时,通常只会显示存在实际值的索引,看起来像是索引从某个位置开始,但实际上数组的索引依然从0开始——只是0到某个位置的索引是空槽,没有元素而已。比如第一段代码splice后的数组,console.log(arr)会显示[empty, 1, 2, 3],但它的长度是4,索引0确实存在(只是为空槽)。

避免此类问题的方法

如果需要创建指定长度的密集数组,不要用new Array(n),改用以下方式:

// 创建长度为3,每个元素为undefined的密集数组
const arr = Array.from({length: 3});
// 或者
const arr = new Array(3).fill(undefined);

这样创建的数组后续splice等操作行为会和字面量创建的数组完全一致。

内容的提问来源于stack exchange,提问作者JSmith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:00:28