浅拷贝仅复制数组第一层结构,基本类型独立,引用类型仍共享内存;如[...arr]、slice()等均属浅拷贝,修改嵌套对象会同步影响原数组。

数组克隆的 shallow copy(浅拷贝)本质是“复制一层结构,不穿透嵌套”。它创建一个新数组,但只对第一层元素做值拷贝——基本类型(如数字、字符串)被真正复制;引用类型(如对象、子数组、函数)仍共享原内存地址。
浅拷贝只管“外层”,不管“里层”
比如数组 [1, {name: 'Alice'}, [2, 3]] 浅拷贝后,新数组和原数组:
- 索引
0的1是独立副本,改它不影响对方 - 索引
1的对象{name: 'Alice'}是同一块堆内存,改新数组[1].name会同步反映在原数组上 - 索引
2的子数组[2, 3]同样共用地址,新数组[2].push(4)会让原数组的子数组也变成[2, 3, 4]
常见浅拷贝写法及效果一致
以下所有方式都只做浅拷贝:
-
arr.slice()或arr.slice(0) -
[...arr](扩展运算符) -
arr.concat()或[].concat(arr) Array.from(arr)Object.assign([], arr)
它们都返回新数组,但内部若含对象或数组,就仍是引用共享——不是“不够快”,而是设计如此。
什么时候会踩坑?
典型误用场景:
- 从 state 拿出一个含对象的数组做编辑,直接
const newList = [...oldList],然后newList[0].price = 99→ 原 state 也被改了 - 表单数据预处理时,用
JSON.parse(JSON.stringify())以外的方式克隆嵌套结构,结果提交时发现原始数据已变 - 多人协作中,有人以为
slice()就“安全”,没意识到深层引用仍连通
验证是否真浅拷贝:改内层,看原数组
最直接的判断方法:
const a = [1, {x: 2}];
const b = [...a];
b[1].x = 99;
console.log(a[1].x); // 输出 99 → 说明是浅拷贝
只要修改拷贝后数组里的对象/数组属性,原数组对应位置也变了,那就一定是浅拷贝。











