javascript数组默认不自动深拷贝,多数复制操作属浅拷贝:仅新建数组容器,内部引用类型(对象、子数组)仍共享内存地址;修改嵌套元素会导致原数组同步变化,需根据是否修改引用类型决定是否使用深拷贝。

JavaScript 中数组创建时默认不自动深拷贝,多数“复制”操作实际是浅拷贝——只新建数组容器,内部元素仍共享引用。是否需要深拷贝,取决于你后续会不会修改嵌套的引用类型(如对象、子数组)。
哪些数组操作属于浅拷贝
以下方法创建新数组,但仅复制第一层:元素是基本类型(数字、字符串等)时完全独立;元素是对象或数组时,新旧数组指向同一内存地址。
-
扩展运算符:
[...arr] -
slice():
arr.slice()或arr.slice(0) -
concat():
arr.concat()或[].concat(arr) -
Array.from():
Array.from(arr) -
解构赋值:
const [...newArr] = arr
浅拷贝引发的问题场景
当你修改数组中某个对象或子数组的属性时,原始数组也会同步变化——因为它们共用同一份底层数据。
例如:const original = [1, {name: 'Alice'}, [2, 3]];<br>const copied = [...original];<br>copied[1].name = 'Bob'; // 修改嵌套对象<br>copied[2].push(4); // 修改嵌套数组<br>console.log(original); // → [1, {name: 'Bob'}, [2, 3, 4]]
这种联动在表单编辑、状态暂存、撤销/重做等场景中容易引发意外副作用。
何时必须用深拷贝
满足任一条件就该考虑深拷贝:
- 数组中包含对象、嵌套数组、Date、RegExp 等引用类型,且你计划修改它们
- 需确保原始数据绝对不可变(如 Redux state、Vue reactive 副本)
- 要实现「编辑-取消」逻辑,避免直接污染源数据
实用深拷贝方案选择
没有银弹,按需求选:
-
简单纯数据结构(无函数、undefined、Symbol、循环引用):用
JSON.parse(JSON.stringify(arr)),轻量快捷 -
含函数、日期、正则、Map/Set 或需处理循环引用:用 Lodash 的
_.cloneDeep(arr) - 想控制细节或避免第三方依赖:手写递归克隆函数,对每个元素判断类型后分别处理
注意:structuredClone()(现代浏览器支持)是原生推荐方案,能安全处理大多数复杂类型,包括 Map、Set、Date、BigInt 和可转移对象,且支持循环引用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











