扩展运算符(Spread operator)在数组与对象中的行为是否存在差异?
理解扩展运算符的浅拷贝行为:数组基本类型 vs 引用类型
这是个典型的JavaScript浅拷贝问题,咱们来把这个现象拆解明白:
先修正你代码里的小笔误
你代码里有几个拼写错误,比如console.log(copy)应该是console.log(copiedArray),arr应该是array,修正后的完整代码是:
const array = [12,40,63,21,22,32]; const copiedArray = [...array]; console.log(copiedArray); array[0] = 92; console.log(array, copiedArray); const p1 = [{name:'Arabh' , age:39} ,{name:'Sana' , age:33}]; const p2 = [...p1]; p1[0].name = 'Samir'; console.log(p1,p2);
为什么两种场景表现不同?
核心原因是扩展运算符实现的是浅拷贝,它对数组元素的处理方式取决于元素的类型:
- 基本类型(数字、字符串、布尔值等):这些类型的值直接存在栈内存里,扩展运算符会复制它们的实际值到新数组。所以当你修改原数组的
array[0]时,只是改变了原数组对应位置的值,新数组copiedArray里保存的是原来的12,不会跟着变化。 - 引用类型(对象、数组等):这些类型的实际数据存在堆内存,变量里保存的是指向堆内存的引用地址。扩展运算符复制的只是这个引用地址,所以
p1[0]和p2[0]指向的是同一个堆内存里的对象。当你修改p1[0].name时,其实是在修改堆内存里那个对象的属性,两个数组里的引用都指向这个对象,所以都会看到变化。
如何实现深拷贝(让对象数组修改原对象不影响新数组)
如果想要完全复制对象数组,让原对象和新对象互不影响,可以用这些方法:
- 简单场景用
JSON.parse(JSON.stringify(数组)):注意这个方法不能处理函数、Symbol类型、循环引用的对象 - 手写递归深拷贝函数,遍历每个元素,遇到引用类型就递归复制
- 用成熟的工具库,比如Lodash的
_.cloneDeep方法
内容的提问来源于stack exchange,提问作者Sangita Das
相关产品推荐
相关产品推荐

