清空数组的几种姿势
清空数组是一个高频操作:重置列表、回收旧数据、初始化组件状态,都绕不开它。JavaScript 提供了多种清空方式,但它们在语义、性能和对引用的影响上差别很大。
五种清空方式
给定以下初始数据:
js
let list = [1, 2, 3, 4, 5];
let anotherRef = list; // 另一个变量引用了同一个数组方式一:直接赋值为空数组 list = []
js
list = [];
console.log(list); // []
console.log(anotherRef); // [1, 2, 3, 4, 5]如果存在其他变量引用原数组,原数组并不会被清空——list 只是指向了新数组,旧数组依然完整地存在于内存中,anotherRef 依然可以访问它。这种方式适用于单引用场景:当数组只有一份引用时,将变量重新指向空数组,旧数组失去全部引用后被垃圾回收器回收。
方式二:splice 原地删除
js
list.splice(0, list.length);splice(0, list.length) 从索引 0 开始删除 list.length 个元素,在原数组上操作,时间复杂度 O(n)。共享同一引用的其他变量也会看到空数组。
方式三:pop 循环逐个删除
js
while (list.length) {
list.pop();
}从尾部逐个弹出元素,时间复杂度 O(n),原地操作。每次 pop 都会触发一次数组长度变更,性能弱于 splice。
方式四:shift 循环逐个删除
js
while (list.length) {
list.shift();
}时间复杂度 O(n²),原因是每次 shift 删除第一个元素后,后续所有元素需要向前移动一位。这是五种方式中效率最低的,不建议用于清空大数组。
方式五:直接设置 length = 0
js
list.length = 0;这是最简洁高效的清空方式:原地操作,所有对同一数组的引用同步清空,时间复杂度 O(1)(或接近常量时间,取决于引擎实现)。在 V8 等现代引擎中,将 length 设为 0 会直接截断内部存储,不需要逐个删除元素。
选型建议
| 方式 | 是否原地清空 | 时间复杂度 | 使用场景 |
|---|---|---|---|
list = [] | 否 | O(1) | 单引用、不关心旧数组时 |
splice(0, len) | 是 | O(n) | 需要原地清空、兼容性好 |
while + pop | 是 | O(n) | 需要逐个处理元素 |
while + shift | 是 | O(n²) | 不推荐 |
length = 0 | 是 | ~O(1) | 推荐,最彻底的清空 |
如果不需要保留对原数组的引用,list = [] 最直接。如果存在多个引用且需要同步清空,list.length = 0 是最优选择——它能保证所有引用方看到的都是空数组,同时性能表现也是最好的。