为何使用扩展语法(spread syntax)克隆数组时空槽会被替换为undefined?
数组克隆时空槽变undefined的原因及解决办法
你遇到的情况是:用扩展语法[...arr]克隆包含空槽的稀疏数组时,原数组里的空槽会被替换成undefined,而非保留空槽状态。这是由JavaScript扩展语法的遍历逻辑决定的:
核心原因
JavaScript里的数组空槽(稀疏数组的空位)和undefined是完全不同的概念:
- 空槽:数组在该索引位置没有任何元素,调用
arr.hasOwnProperty(index)会返回false undefined:是一个实际存在的元素值,arr.hasOwnProperty(index)返回true
扩展语法[...arr]、Array.from()以及map、filter这类数组方法,在遍历数组时会把空槽当作undefined处理——它们会为每个索引位置都添加一个元素,空槽对应的位置就被填充为undefined,最终得到的是一个“密集数组”,而非原有的稀疏数组。
你可以用这段代码直观验证两者的区别:
const arr = [1, , undefined]; // 原数组的空槽(索引1)没有自有属性 console.log(arr.hasOwnProperty(1)); // false // 索引2是实际存在的undefined元素 console.log(arr.hasOwnProperty(2)); // true const clone = [...arr]; // 克隆后索引1变成了实际的undefined元素 console.log(clone.hasOwnProperty(1)); // true console.log(clone.hasOwnProperty(2)); // true
保留空槽的克隆方法
如果需要克隆数组并保留原有的空槽,可以用以下几种方法:
1. 使用Array.prototype.slice()
slice是专为数组设计的克隆方法,会完整保留稀疏数组的空槽:
const arr = [1, "", , null, undefined, false, , 0]; const clone = arr.slice(); console.log(clone); // 空槽与原数组完全一致
2. 手动创建数组并赋值
通过遍历原数组索引,仅对存在自有属性的索引赋值:
const arr = [1, "", , null, undefined, false, , 0]; const clone = new Array(arr.length); for (let i = 0; i < arr.length; i++) { if (arr.hasOwnProperty(i)) { clone[i] = arr[i]; } } console.log(clone); // 空槽被保留
3. 使用Object.assign()
Object.assign会按对象的自有属性复制,因此也能保留数组空槽:
const arr = [1, "", , null, undefined, false, , 0]; const clone = Object.assign([], arr); console.log(clone); // 空槽保留
内容的提问来源于stack exchange,提问作者DecPK
相关产品推荐
相关产品推荐

