JavaScript/TypeScript Spread Operator 混淆行为:数组复制写法差异
JavaScript/TypeScript扩展运算符在对象与数组字面量中的行为差异
问题重现
假设我们有一个包含对象的数组,尝试浅拷贝时两种扩展写法的差异:
const test = [{ id: 1 }, { id: 2 }]; // 对象字面量扩展数组 const objSpread = { ...test }; console.log(objSpread); // { '0': { id: 1 }, '1': { id: 2 } } console.log(Array.isArray(objSpread)); // false // 数组字面量扩展数组 const arrSpread = [...test]; console.log(arrSpread); // [{ id: 1 }, { id: 2 }] console.log(Array.isArray(arrSpread)); // true
行为名称与原因
这种差异属于扩展运算符在不同字面量上下文的重载行为,核心原因在于数组的本质与两种扩展语法的处理逻辑不同:
- 数组的本质:数组是特殊的类数组对象,它的可枚举属性包括非负整数类型的索引键(如
0、1),而length等核心属性是不可枚举的。 - 对象字面量扩展
{ ...iterable }:该语法会遍历目标的所有可枚举属性,将属性名和值复制到新对象中。处理数组时,只会把数组的索引键作为对象的键,生成一个普通对象,而非数组实例。 - 数组字面量扩展
[ ...iterable ]:该语法会调用目标的Symbol.iterator迭代器,遍历数组元素并依次添加到新数组中,最终生成新的数组实例,保留数组的所有特性(如length属性、数组原型方法)。
总结
浅拷贝数组必须使用数组字面量的扩展语法[...arr];若误用对象字面量扩展数组,得到的是包含索引键的普通对象,不具备数组的行为特性。
内容的提问来源于stack exchange,提问作者Rakis Friski
相关产品推荐
相关产品推荐

