news 2026/10/22 20:54:36

JavaScript 的深拷贝与浅拷贝——复制一个对象为什么这么难

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript 的深拷贝与浅拷贝——复制一个对象为什么这么难

引言

在 JS 里复制一个对象,看起来简单,做起来处处是坑。你以为是复制了一份独立的数据,结果改了新对象,原对象也跟着变。或者你小心翼翼地复制了一层,结果嵌套里面的对象还是共享的。问题就出在浅拷贝和深拷贝的区别上。这篇文章只讲这一个问题,把复制的逻辑讲清楚。

一、问题的根源:引用类型

要理解拷贝,先要理解引用类型。

原始类型的变量,存的是值本身。复制一个数字变量,得到的是独立的两份值,改一个不影响另一个。

引用类型的变量,存的是地址。复制一个对象变量,复制的只是地址,两个变量指向同一个物体。改其中一个,另一个看到的也是改后的结果。

所以,复制对象不能简单赋值。必须创建新对象,把原对象的内容搬过去。但搬到什么程度,就是浅拷贝和深拷贝的分界线。

二、浅拷贝:只复制第一层

浅拷贝,顾名思义,只复制对象的第一层。

它创建一个新对象,把原对象第一层的属性值复制过来。如果属性值是原始类型,复制的是值,互不影响。如果属性值是引用类型,复制的是地址,新对象和原对象仍然共享那个嵌套对象。

所以,浅拷贝之后,改新对象的第一层原始属性,原对象不受影响;但改新对象里嵌套的对象,原对象也会变。

浅拷贝的实现方式有多种:展开运算符、对象合并方法、数组切片方法等,本质上都是只处理第一层。

三、深拷贝:递归复制所有层

深拷贝,是要得到一个完全独立的新对象,无论嵌套多少层,都不共享。

它的思路是递归:遇到原始类型直接复制值,遇到引用类型就新建一个同类型容器,再递归复制里面的内容。一层层往下,直到所有层级都复制完。

深拷贝之后,改新对象的任何地方,原对象都不会受影响。两个对象彻底独立。

四、深拷贝的难点

深拷贝听起来简单,实际实现要考虑很多情况。

第一,循环引用。对象 A 引用了 B,B 又引用了 A。递归复制时会无限循环,导致栈溢出。必须记录已经复制过的对象,遇到重复的直接复用,才能打断循环。

第二,特殊类型。日期、正则、映射、集合这些类型,不能简单当作普通对象处理,需要分别判断并特殊处理,否则复制出来的东西会丢失原有特性。

第三,函数。函数也是对象,但通常不复制函数体,而是直接共享引用。深拷贝一般只处理数据,不处理行为。

第四,原型链。简单递归会丢失原对象的原型,复制出来的对象可能不再是原来的类型。需要额外处理原型关系。

第五,性能。深拷贝要遍历所有层级,对象越大越慢。对大对象做深拷贝,可能造成明显卡顿。

五、常用的深拷贝方式及其局限

手动递归是最可控的方式,可以根据需求处理各种特殊情况,但代码量大,容易漏掉边界情况。

序列化再反序列化是一种取巧方式:把对象转成字符串,再转回对象。简单,但有明显局限:会丢失函数、日期会变成字符串、映射和集合会丢失、循环引用直接报错。只适合纯数据且结构简单的场景。

结构化克隆是较新的浏览器能力,能处理更多类型,也支持循环引用,但并非所有环境都支持,且不能复制函数。

第三方库提供了成熟的深拷贝实现,考虑了大量边界情况,但引入依赖需要权衡体积。

没有一种方式完美适用于所有场景,选择取决于数据类型和运行环境。

六、什么时候用浅拷贝,什么时候用深拷贝

浅拷贝够用的场景:对象只有一层,或者嵌套部分本来就不需要独立;你明确知道哪些部分共享、哪些部分独立;性能敏感,不想付出深拷贝的代价。

必须深拷贝的场景:需要完全独立的数据副本,修改副本不能影响原数据;对象结构复杂且嵌套深;要把数据传给不可信的外部逻辑,防止被意外修改。

很多时候,浅拷贝加手动处理特定嵌套字段,比无脑深拷贝更高效。不是越深越好,而是按需复制。

七、不可变思维

现代前端开发中,越来越流行不可变的思路:不修改原对象,每次变化都产生新对象。

这种思路下,浅拷贝用得非常频繁。因为只要保证每次修改都创建新对象,不直接改原对象,就能实现状态的可追踪。对于嵌套结构,可以只复制变化路径上的节点,其余部分共享,既保证独立性又节省性能。

理解浅拷贝和深拷贝,是掌握这种思维的基础。

八、总结

浅拷贝只复制第一层,嵌套的引用仍然共享;深拷贝递归复制所有层,得到完全独立的对象。深拷贝要处理循环引用、特殊类型、性能等问题,没有一种方式放之四海而皆准。实际开发中,要根据数据结构和需求选择复制深度,而不是一律深拷贝。理解这个区别,你就能避免"改了副本原对象也变"的坑,也能在性能敏感时做出合理取舍。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 20:51:32

1.使用cephadm部署ceph集群(ceph)

一、前言 本文主要介绍如何通过cephadm部署ceph集群。 环境说明: 部署方法:cephadm 操作系统:ubuntu22.04 ceph版本:S版本 部署过程中需要拉ceph镜像,可以直接去我个人镜像仓库拉取 二、架构图 ceph的架构图如下&am…

作者头像 李华
网站建设 2026/10/22 20:34:01

【2025】RobotStudio 2024安装教程保姆级一键安装教程(附安装包)

文章目录RobotStudio下载RobotStudio 2024详细安装步骤安装前准备与解压启动RobotStudio安装程序安装向导操作自定义安装位置首次运行与许可设置RobotStudio常见问题与解决方案本教程为您带来RobotStudio 2024的保姆级一键安装指南。RobotStudio是瑞士ABB公司推出的机器人编程软…

作者头像 李华
网站建设 2026/10/22 20:29:24

PJ85718DM+TM4C129X温控系统:高精度传感与工业以太网边缘闭环设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 20:24:16

红黑树详解:性质、旋转、插入删除与工程实践

红黑树,咕咕咕!—— 聊聊这颗让无数人“学废了”的平衡树我猜你点进这篇文章,多半是因为看到了“咕咕咕”这三个字。这词儿在咱们程序员圈子里太亲切了——说好的周末看红黑树,结果刷了一下午短视频;说好的下周一投简历…

作者头像 李华
网站建设 2026/10/22 20:18:44

模具术语中英对照:从静态PDF到团队可维护词库

简介:面向模具设计、制造与外贸从业者的专业术语对照手册,系统整理冲压模具领域高频常用语的中英文表达。内容按模具种类、工序、零件、公差、冲床相关等模块分类,涵盖连续模、冲孔模、机械手模等模具名称,冲孔、剪边、成形、折弯…

作者头像 李华
网站建设 2026/10/22 20:18:40

ADAMS两轮机器人运动仿真:从虚拟样机到调参实战

简介:一份基于ADAMS与MATLAB的两轮机器人运动研究文档,面向机器人、机械电子及自动化方向的在校生和入门研究者,系统展示了从模型简化、控制设计到动力学仿真的完整流程。文档先借助MATLAB对机器人模型进行参数与受力分析,并基于倒…

作者头像 李华