深拷贝确保对象各层级完全独立,修改副本不影响原对象;浅拷贝仅复制第一层,嵌套对象仍共享引用;序列化用于数据传输或存储,非专为拷贝设计,会丢失函数、Date等类型。

区分 JavaScript 对象拷贝与序列化,关键看你要解决的问题是“数据隔离”还是“数据交换”。拷贝关注的是内存中对象的独立性,序列化关注的是数据格式的可传输性与持久性。
什么时候用浅拷贝?
适用于只读取、仅修改第一层属性,且能接受嵌套引用共享的场景。
- 表单编辑前备份初始值(如 Vue/React 中的临时编辑态)
- 合并配置对象,比如
Object.assign({}, defaults, userConfig) - 数组扁平化操作前保留原数组结构(
[...arr]或arr.concat())
注意:若对象含 city: { name: '天津' } 这类嵌套对象,改 copy.city.name 会同步影响原对象。
什么时候必须用深拷贝?
当对象存在多层嵌套,且修改副本绝不能波及原始数据时。
立即学习“Java免费学习笔记(深入)”;
- 状态管理中保存历史快照(如撤销/重做功能)
- 将 API 响应数据传给多个组件并允许各自修改
- 测试中构造隔离的测试数据,避免用例间污染
推荐优先使用 structuredClone()(现代浏览器 & Node.js 17.0+),它支持 Date、Map、Set、RegExp 等,还能处理循环引用。兼容性不足时再退到 JSON 方案或自定义递归函数。
什么时候该用序列化?
不是为了复制对象,而是为了存储、传输或跨环境交换数据。
- 把对象存入
localStorage(只能存字符串) - 通过
fetch发送请求体:JSON.stringify(data) - 服务端渲染(SSR)时将初始状态注入 HTML 的
<script>标签
注意:JSON.stringify/parse 本质是“序列化 + 反序列化”,它能实现深拷贝只是副作用;但它会丢弃 function、undefined、Symbol、Date(转成字符串)、RegExp 等,不是真正的通用拷贝手段。
拷贝和序列化混用的典型误区
有人用 JSON.parse(JSON.stringify(obj)) 来“保险起见地深拷贝”,结果遇到 Date 变字符串、NaN 变 null、循环引用直接报错。这不是拷贝逻辑错了,而是误把序列化工具当成了通用拷贝 API。
真正需要拷贝时,先判断结构复杂度和运行环境,再选 structuredClone → 自定义递归 → JSON(仅限纯数据);需要存或传时,才走 JSON.stringify 流程。


















