浅拷贝只复制数组第一层元素,嵌套对象或数组仍共享引用;深拷贝递归复制所有层级,新旧数组完全独立、修改互不影响。

数组的浅拷贝只复制第一层元素,内部若含对象或嵌套数组,仍共享引用;深拷贝则递归复制所有层级,新旧数组完全独立,修改互不影响。
浅拷贝:只断开第一层引用
浅拷贝创建一个新数组,但其中的元素如果是引用类型(比如对象、子数组),拷贝的是地址而非内容。改拷贝数组里的嵌套项,原数组也会跟着变。
- 常见方法:`arr.slice()`、`arr.concat()`、`[...arr]`、`Array.from(arr)`
- 典型陷阱:`let arr = [1, {x: 2}]; let copy = [...arr]; copy[1].x = 99;` → 原数组 `arr[1].x` 也变成 99
- 适用场景:数组元素全是基本类型(数字、字符串等),或你明确只读、不改深层结构
深拷贝:彻底隔离所有层级
深拷贝会遍历整个数组结构,对每个嵌套的对象、数组都新建内存空间,确保拷贝后任意层级的修改都不影响原始数组。
-
简单可靠方案:现代环境首选
structuredClone(arr)—— 原生支持、能处理 Date、Map、Set、循环引用,且保留函数以外的大部分类型 -
兼容老环境:用 Lodash 的
_.cloneDeep(arr),自动处理正则、日期、稀疏数组等边界情况 - 慎用方案:`JSON.parse(JSON.stringify(arr))` 能深拷贝,但会丢掉函数、undefined、Date 对象、RegExp、NaN 和循环引用
怎么选?看结构和后续操作
别凭感觉,动手判断:
- 数组里只有数字、字符串、布尔值?→ 浅拷贝足够
- 含对象、子数组,并且你要 push/splice/赋新值给
copy[0].name或copy[1][0].id?→ 必须深拷贝 - 要传给第三方库(如图表 setData、表单校验)?→ 默认按深拷贝处理,除非文档写明“只读”
验证是否真正隔离
改完拷贝数组后,立刻检查原数组对应路径:
- 比如
copy[2].items[0].status = 'done' - 马上执行
console.log(original[2].items[0].status) - 输出不同 → 深拷贝成功;输出相同 → 还在共享,换方法重试

















