JS使用 splice(0) 清空数组会保留引用吗
深入解析在 JavaScript 中使用 splice(0) 清空数组是否会保留原有引用的底层机制,结合内存堆栈模型、多变量共享引用联动、执行步骤推导与选型决策,全面解答清空数组的最佳实践。
核心结论:会保留引用。在 JavaScript 中执行 arr.splice(0) 属于典型的原地修改(In-place mutation)操作。它直接在原数组占用的堆内存空间上剔除所有元素,并将其 length 属性重置为 0,而不会开辟新的内存对象赋予变量。因此,所有指向该数组对象的其他变量、对象属性或函数作用域引用,都会即时感知到数组变为空数组。
一、JavaScript 引用传递与 splice 的底层机制
在 JavaScript 中,数据类型被严格划分为基本类型(Primitive Types)与引用类型(Reference Types)。数组(Array)本质上是特殊的对象,属于引用类型。
当声明一个数组 const arr = [1, 2, 3] 时,JavaScript 引擎在栈内存中为变量 arr 分配空间,存储的是该数组在堆内存中的物理地址指针(例如 0x00A1FB)。如果在后续逻辑中将该数组赋值给另一个变量:
const original = ['Vue', 'React', 'Angular'];
const copy = original; // 传递的是堆内存地址指针
此时,original 和 copy 两个独立的栈变量,内部保存的完全是同一个堆内存地址。判断清空数组的方式是否“保留引用”,关键看该操作是在原堆内存地址上修改内部数据,还是在堆内存中新建了一个全新的数组实例并将栈指针重定向。
二、splice(0) 的完整执行流程与双重效果
根据 ECMAScript 规范,Array.prototype.splice(start, deleteCount, ...items) 具有以下关键行为准则:
- 当仅传入参数
0(即start = 0且省略deleteCount)时,JavaScript 引擎会将deleteCount隐式计算为length - start,也就是从第 0 个索引开始,删除后续所有元素。 - 引擎在原数组内部依次移除元素,并将数组属性
length更新为0。 - 重要伴随动作:引擎会同时构建一个全新的数组,将被删除的所有元素依次浅拷贝进该新数组中,并作为表达式的返回值(Return Value)传回。
这意味着执行 const removed = arr.splice(0) 时,实际上产生了两个维度的产物:
- 维度一(就地清空):原数组
arr本身被清空,元素被清退,引用被完好保留; - 维度二(返回值收集):变量
removed获得了包含原有全部元素的新数组。
三、实际代码示例与多引用联动验证
1. 多个局部变量共享引用的场景
在业务逻辑中,如果将数据源赋值给了多个变量,测试 splice(0) 对引用的影响最为直观:
// 1. 初始化原始数组
const originalList = [101, 102, 103];
// 2. 共享引用给 secondaryList
const secondaryList = originalList;
// 3. 对 originalList 执行 splice(0)
const deletedItems = originalList.splice(0);
// 4. 验证结果
console.log(originalList); // 示例输出: []
console.log(secondaryList); // 示例输出: [] (同步变空,引用得以保留)
console.log(deletedItems); // 示例输出: [101, 102, 103] (被删除的元素副本)
console.log(originalList === secondaryList); // 示例输出: true (仍然指向同一内存地址)
2. 函数参数传递与副作用场景
在 JavaScript 中,函数参数传递属于按值传递(Pass by value),但当参数为引用类型时,传递的值即为内存地址指针。如果在函数内部使用 splice(0),该操作会直接穿透函数作用域,修改外部的实际数组:
function clearCache(targetArray) {
// 必须原地修改,以让调用者持有的原数组也同步变空
targetArray.splice(0);
}
const appCache = ['session_1', 'session_2'];
clearCache(appCache);
console.log(appCache); // 示例输出: [] (外部数组确实被清空了)
反之,如果错误地在函数内使用 targetArray = [],由于该赋值仅是将函数内部的局部形参指针指向了新数组,外部的 appCache 完全不会受到任何影响,导致业务缓存未能按预期清空。
四、常见清空数组方案横向对比
在 JavaScript 中,清空数组主要有以下四种常见写法。它们在是否保留引用、返回值特性以及内存执行开销上存在明显差异:
| 实现方式 | 是否保留原引用 | 是否有返回值 | 额外内存分配 | 典型适用场景 |
|---|---|---|---|---|
arr.splice(0) |
是(保留引用) | 有(返回被删元素的副本) | 有(需要开辟新数组保存被删项) | 需要保留引用,同时还要取出旧数据处理 |
arr.length = 0 |
是(保留引用) | 无(返回设置后的数值 0) | 无(纯指针与计数器收缩) | 绝大多数仅需原地清空数组的首选 |
arr = [] |
否(重新指向新数组) | 无 | 极低(创建空数组) | 局部变量,无其他外部模块共享引用 |
arr.splice(0, arr.length) |
是(保留引用) | 有(同 splice(0)) | 有 | 语义等同于 splice(0),写法略显冗长 |
虽然 splice(0) 能可靠保留引用,但因为它总是会实例化一个装有全部旧元素的新数组返回,如果待清空的数组包含数十万甚至数百万条记录,splice(0) 会在瞬间造成巨大的内存分配峰值并加重垃圾回收(GC)负担。如果仅仅为了清空数组而不需要旧元素,请优先选用 arr.length = 0。
五、清空方案技术选型决策树
面对具体的业务场景,应当如何科学选择清空数组的语法?可以通过以下决策路径进行判断:
六、总结与使用建议
回到最初的问题:JS使用 splice(0) 清空数组会保留引用吗?
答案是完全会保留引用。在需要让所有共享该数组的模块或外部函数同步清空、且原变量使用 const 声明不能重新赋值时,splice(0) 能够完全满足保留引用的需求。
在日常开发中的选型建议:
- 如果你不仅要原地清空数组,还想顺便拿到被删掉的所有元素进行后续归档或操作,那么
const removedItems = arr.splice(0)是极其优雅且唯一语义直接的解法; - 如果你仅仅是想要清空数组并保留引用,推荐使用更精炼、性能更高的
arr.length = 0; - 如果当前数组仅在当前局部作用域内使用、不存在任何跨模块共享引用,直接使用
arr = []即可。
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
JavaScript新手常犯的编码错误与最佳实践指南
2026-11-04 22:12:38








