展开运算符仅浅拷贝,嵌套数组仍共享引用;修改副本会同步影响原对象,需用structuredClone()、手动逐层展开或JSON方案实现真正克隆。

展开运算符(...)本身只能进行浅拷贝,对包含数组的复杂对象直接使用会出问题——数组引用仍被共享,修改副本会影响原对象。
为什么直接展开无法真正克隆嵌套数组
展开运算符只复制对象第一层属性。如果某属性是数组,它复制的是该数组的引用,而非数组内容本身。
- 例如:
const obj = { items: [1, 2, 3] }; -
const clone = { ...obj };→clone.items === obj.items为 true - 执行
clone.items.push(4),原对象obj.items也会变成[1, 2, 3, 4]
正确克隆:逐层处理嵌套数组
要真正分离数组,需在展开的同时对数组属性做深拷贝。常用方式是结合展开与数组展开或结构赋值。
- 对已知结构的对象,可手动展开数组:
const clone = { ...obj, items: [...obj.items] }; - 若数组内还有对象,继续展开:
items: obj.items.map(item => ({ ...item })) - 支持多层嵌套时,推荐用递归函数或
structuredClone()(现代环境)
更通用的方案:structuredClone()(推荐)
ES2022 引入的 structuredClone() 可安全深拷贝大多数值,包括数组、普通对象、Map、Set 等(不支持函数、undefined、Symbol 等)。
立即学习“Java免费学习笔记(深入)”;
const clone = structuredClone(obj);- 无需关心嵌套层级,自动处理数组及内部对象
- 兼容性注意:Chrome 98+、Firefox 94+、Safari 16.4+;旧环境需 polyfill 或降级为 JSON 方案
备选方案:JSON 序列化(简单但有局限)
适用于纯数据对象(无函数、Date、RegExp、undefined、循环引用):
const clone = JSON.parse(JSON.stringify(obj));- 能彻底断开数组和对象引用
- 缺点明显:丢失方法、日期变字符串、过滤 undefined 和 Symbol、不支持 BigInt 和循环引用
不复杂但容易忽略——关键在于识别哪些字段是引用类型,再针对性深拷贝。优先用 structuredClone,次选手动展开 + 数组映射,慎用 JSON 方案。


















