浅拷贝仅复制第一层属性:基本类型值被真实复制,引用类型只复制内存地址,新旧对象共享嵌套数据;它忽略原型链、不可枚举属性及symbol键,不触发getter/setter,也不保留构造信息。

JavaScript浅拷贝的深度边界就是第一层属性。它不关心对象内部结构有多深,只做“表面复制”:基本类型值被真正复制,引用类型(对象、数组等)只复制其内存地址,新旧对象仍指向同一块堆内存。
浅拷贝到底复制了什么?
它只处理对象自身的可枚举属性,且仅限顶层:
- 复制属性名和对应值——值是数字、字符串、布尔等就真拷贝一份;
- 值是对象、数组、函数、Date 等引用类型时,只拷贝那个“指针”,不是内容;
- 忽略原型链上的属性、不可枚举属性、Symbol 键(除非显式处理);
- 不触发 getter/setter,也不保留对象的构造信息(比如 new Date() 拷出来只是普通对象)。
为什么嵌套对象改一个,两个都变?
因为嵌套部分没被复制,只是“共享引用”。例如:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
const copy = { ...user };
copy.profile.age = 31;
console.log(user.profile.age); // 31 ← 原对象也被改了
这里 profile 是个对象引用,{...user} 只把 profile 这个地址复制给了 copy,user.profile 和 copy.profile 指向同一个对象。
想安全处理嵌套,不能靠浅拷贝
浅拷贝天生不负责嵌套,所以遇到多层结构时,必须换策略:
- 如果嵌套层级固定且简单(比如最多两层),可手动逐层展开:
{ ...obj, profile: { ...obj.profile } }; - 若不确定深度或结构动态,直接上深拷贝方案,比如
structuredClone(obj)(现代浏览器支持,能处理 Map/Set/Date/RegExp 和循环引用); - 兼容老环境可用
lodash.cloneDeep(),它覆盖多数类型,但注意不保留自定义类的方法和某些宿主对象(如 DOM 节点); - 避免用
JSON.parse(JSON.stringify(obj)),它会丢掉函数、undefined、Date、RegExp、Symbol 和循环引用,不是真正可靠的深拷贝。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










