首页
/ 在 freeCodeCamp 基础数据结构课程中掌握 Array.splice():从数组中间删除元素

在 freeCodeCamp 基础数据结构课程中掌握 Array.splice():从数组中间删除元素

2026-09-06 18:29:05作者:农烁颖Land

导读

Array.prototype.splice() 是 JavaScript 中最强大的数组方法之一,它不仅能从任意位置一次性删除多个连续元素,还能原地修改原数组并返回被移除元素的集合。这篇指南围绕 freeCodeCamp「JavaScript 算法与数据结构」认证下 Basic Data Structures(基础数据结构)模块中的 Remove Items Using splice() 这一实战挑战展开,从零索引原理、参数语义到可运行代码逐层剖析,并结合作战题目自带的测试断言与官方解法,帮助你彻底掌握用 splice() 完成数组“定点批量删除”的实战能力。

挑战概览:为什么需要 splice()?

本挑战文件位于 curriculum/challenges/english/blocks/basic-data-structures/587d78b2367417b2b2512b10.md,在课程体系中的定位可以这样理解:

该挑战的前置铺垫是 Remove Items from an Array with pop() and shift(),后续衔接是 Add Items Using splice()

在学完 push() / unshift()(从尾/头部添加)和 pop() / shift()(从尾/头部删除)之后,会出现一个明显的能力缺口:

  • pop() 只能删掉数组末尾的一个元素;
  • shift() 只能删掉数组开头的一个元素;
  • 当你想删掉数组中间某个位置的元素,或者想一次删除多个元素时,这两个方法都无能为力。

这正是 splice() 的用武之地。如挑战 description 中所述:

splice() allows us to do just that: remove any number of consecutive elements from anywhere in an array.

即:splice() 可以从数组的任意位置移除任意数量的连续元素

参数语义与前两个参数详解

挑战原文指出,splice() 最多可以接收 3 个参数,但本挑战先聚焦前两个。

array.splice(start, deleteCount);

第一个参数 start:开始删除的索引

  • 它是一个整数,代表调用 splice() 的数组上的索引(位置)。
  • JavaScript 数组是**从零开始索引(zero-indexed)**的,所以要指向数组的第一个元素必须写 0。这一点挑战原文明确强调:“arrays are zero-indexed, so to indicate the first element of an array, we would use 0”。
  • start 表示从此索引处开始删除元素

第二个参数 deleteCount:要删除的元素个数

  • 它也是一个整数,代表从 start 开始向后数、一共删除多少个元素

综合起来:array.splice(start, deleteCount) 的含义是“从索引 start 开始,向后删除 deleteCount 个连续元素”。

逐步演示:从中间删除

挑战给出的入门例子:

let array = ['today', 'was', 'not', 'so', 'great'];

array.splice(2, 2);

array.splice(2, 2) 的解析过程:

索引 0 1 2 3 4
原数组元素 'today' 'was' 'not' 'so' 'great'
  • 第一个参数 2:从索引 2 开始,对应元素 'not'
  • 第二个参数 2:连续删除 2 个元素,即 'not''so'(索引 2、3)。

操作结束后 array 变成 ['today', 'was', 'great'],与挑战原文结论完全一致。可以看到,删除后剩余元素会自动前移填补空缺,数组长度由 5 变为 3。

splice() 是原地修改并返回被删元素的数组

splice() 的行为与 slice() 有一个极其容易混淆的关键区别:它会原地(in place)修改调用它的数组本身,且其返回值是一个包含所有被删除元素的新数组,而非修改后的原数组。

挑战原文示例:

let array = ['I', 'am', 'feeling', 'really', 'happy'];

let newArray = array.splice(3, 2);
  • array['I', 'am', 'feeling', 'really', 'happy']
  • array.splice(3, 2):从索引 3('really')开始删 2 个元素,即 'really''happy'
  • 原数组 array 被原地修改为 ['I', 'am', 'feeling']
  • 返回值 newArray['really', 'happy']

这里体现了“一鱼两吃”的典型用法:既要保留原数组删除后的结果,又要拿到被删元素去做后续处理。

与 slice() 的对比记忆点

同为数组截取工具,slice(start, end) 不修改原数组并返回副本;而 splice(start, deleteCount) 原地修改原数组并把删除部分作为返回值。凡是看到“原地删除 + 取出被删项”的需求,都应优先考虑 splice()

本挑战的实战任务:让元素之和等于 10

题目要求(instructions)

We've initialized an array arr. Use splice() to remove elements from arr, so that it only contains elements that sum to the value of 10.

即:使用 splice() 从数组 arr 中删除若干元素,使 arr 剩下的元素之和恰好等于 10

起始代码(seed)

题目给出的可运行起始代码(位于该 md 文件的 # --seed-- / --seed-contents-- 段):

const arr = [2, 4, 5, 1, 7, 5, 2, 1];
// Only change code below this line

// Only change code above this line
console.log(arr);

在 freeCodeCamp 中,--seed-contents-- 定义了学习者编辑区中预先填充的代码,用户只能在两行注释之间修改。

解题推理

先计算数组元素的总和:

2 + 4 + 5 + 1 + 7 + 5 + 2 + 1 = 27

目标是剩下的元素和为 10,因此需要删掉的元素之和为:

27 − 10 = 17

观察数组 [2, 4, 5, 1, 7, 5, 2, 1],索引排列如下:

索引 0 1 2 3 4 5 6 7
2 4 5 1 7 5 2 1

连续片段 4 + 5 + 1 + 7 = 17,它们恰好位于索引 1 到 4,是一段连续元素,非常适合用 splice() 一次性删除。删除后剩余 [2, 5, 2, 1],和为 2 + 5 + 2 + 1 = 10,满足题目要求。

官方参考解法(--solutions--)

const arr = [2, 4, 5, 1, 7, 5, 2, 1];
arr.splice(1, 4);
  • 第一个参数 1:从索引 1(值 4)开始;
  • 第二个参数 4:连续删除 4 个元素 4, 5, 1, 7
  • 原数组被原地修改为 [2, 5, 2, 1],元素之和为 10

值得注意的是,该挑战规定只能删除、不能新增元素。如果传入第三个及以上参数,例如 arr.splice(1, 4, 0),虽然同样能得到和 10,却会违反“只删不加”的约束,被下方的测试判定为错误。

逐条拆解测试断言(hints)背后的校验逻辑

该挑战在 md 文件的 # --hints-- 段内置了 4 条自动化断言。freeCodeCamp 的挑战测试使用一个代码归一化工具链:在断言正则前先调用 __helpers.removeJSComments(code) 去除代码中的注释,再用 __helpers.removeWhiteSpace(...) 去掉空白字符,避免因缩进、换行或注释干扰匹配。

断言一:不得改动初始化的数组声明行

assert(
  __helpers.removeWhiteSpace(__helpers.removeJSComments(code)).match(/constarr=\[2,4,5,1,7,5,2,1\];?/)
);

要求代码中必须保留原始声明 const arr = [2, 4, 5, 1, 7, 5, 2, 1];(去除空白与注释后形如 constarr=[2,4,5,1,7,5,2,1];),即不能偷改数据源。

断言二:剩余元素之和必须严格等于 10

assert.strictEqual(
  arr.reduce((a, b) => a + b),
  10
);

使用 arr.reduce((a, b) => a + b) 累加全部剩余元素,并用 strictEqual 严格等于 10。任何和不为 10 的删除方案都会被拒绝。

断言三:必须调用 splice() 方法

assert(__helpers.removeWhiteSpace(__helpers.removeJSComments(code)).match(/arr\.splice\(/));

检查用户代码中是否出现了 arr.splice( 的调用,强制要求使用 splice() 而不是其他手段(例如手动重建数组、使用 filter() 等)。

断言四:splice 只能删除,不能新增元素

assert(
  !__helpers.removeWhiteSpace(__helpers.removeJSComments(code)).match(/arr\.splice\(\d+,\d+,\d+.*\)/g)
);

这是本挑战最容易踩坑的约束:正则 arr\.splice\(\d+,\d+,\d+.*\) 匹配“出现了第三个(数字)参数及之后内容”的调用形式(即 arr.splice(start, deleteCount, item1, ...))。外层 ! 取反,意味着只要检测到添加元素的调用,测试即失败。这从侧面印证了课程的知识点划分:删除只用前两个参数,第三个参数的“边删边加”能力被留给了下一个挑战 Add Items Using splice() 去专门讲解。

方法脉络:从 pop/shift 到 splice 的完整删除工具箱

在 Basic Data Structures 模块中,删除类 API 的教学顺序是有意设计的:

方法 作用位置 删除数量 是否修改原数组 返回值 对应挑战
pop() 数组末尾 每次 1 个 被删除的元素本身 Remove Items from an Array with pop() and shift()
shift() 数组开头 每次 1 个 被删除的元素本身 同上
splice(start, deleteCount) 任意位置 任意个连续元素 由被删元素组成的新数组 本文所在挑战
splice(start, deleteCount, ...items) 任意位置 任意个连续元素,同时插入新元素 由被删元素组成的新数组 Add Items Using splice()

如挑战原文所述,pop()shift() 的共同弱点是“each only allows an array to be modified by a single element at a time”(每次只能修改单个元素),并且只能作用于两端。而 splice() 把“位置选择”和“批量删除”两个能力合二为一,是数组删除场景中最具通用性的方法。

splice() 的通用行为速查(超出本挑战的延伸知识)

虽然本挑战只用到前两个参数与“纯删除”场景,理解以下几点有助于在真实项目中正确使用:

  • 原地修改splice() 直接改写调用它的数组,如需保留副本应先 const copy = [...arr] 或用 slice() 复制;
  • 返回值语义:返回被删除元素构成的新数组;若 deleteCount 为 0,则返回空数组([]);
  • 删除到末尾的兜底:若 deleteCount 超过 start 之后剩余的元素个数,splice() 会删到数组末尾为止;
  • 负索引支持start 可以为负,-1 指向最后一个元素(与许多现代数组方法的约定一致);
  • deleteCount 为 0:此时 splice(start, 0) 不删除任何元素——配合第三个参数即可在指定索引处做“纯插入”,这一能力是下一个挑战的伏笔。

在 freeCodeCamp 平台上如何运行与验证

本挑战属于 challengeType: 1(标准代码题,对应挑战文件 front matter 中的 challengeType: 1)。你可以:

  1. 在 freeCodeCamp 官网「JavaScript Algorithms and Data Structures」认证的 Basic Data Structures 模块中找到 “Remove Items Using splice()” 挑战;
  2. 将种子代码(--seed-contents-- 内容)粘贴到浏览器内置编辑器中,在 “Only change code below this line” 与 “Only change code above this line” 之间补写 arr.splice(1, 4);
  3. 点击运行,观察 console.log(arr) 是否输出 [2, 5, 2, 1]
  4. 提交后由 # --hints-- 中的 4 条断言自动评分,全部通过即完成挑战。

若想在本地复现逻辑,可在任意 Node.js 环境直接执行:

const arr = [2, 4, 5, 1, 7, 5, 2, 1];
arr.splice(1, 4);
console.log(arr); // [2, 5, 2, 1]
console.log(arr.reduce((a, b) => a + b)); // 10

在仓库层面,该挑战的完整定义(描述、指令、断言、种子代码、官方解法)都收敛在 curriculum/challenges/english/blocks/basic-data-structures/587d78b2367417b2b2512b10.md 这一个 Markdown 文件中,这也体现了 freeCodeCamp 课程“单文件自包含、前后挑战按 block 顺序串联”的内容组织方式。

小结

Remove Items Using splice() 这一挑战解决的核心问题是:如何在任意位置批量删除连续元素。它补齐了 pop()/shift() 只能“两端单删”的短板,同时通过“只能删、不能加”的测试约束,把第三个参数的教学任务精准地让位给下一个挑战,体现出课程设计层层递进的特点。掌握 splice(start, deleteCount) 的两个核心参数、零索引定位方式与“返回被删元素数组 + 原地修改原数组”的双重语义,你就能在实际编码中熟练地完成数组的定点清洗与元素抽取。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388