json.parse(json.stringify())不是真正深拷贝:会丢失函数/undefined/symbol、抹平原型链与特殊对象(如date变字符串、regexp变{})、循环引用直接报错,且不支持bigint、nan/infinity转null等。

JSON 方法(JSON.parse(JSON.stringify(obj)))确实能实现深拷贝,但它的性能开销并不低,且存在明显局限性——它不是通用深拷贝方案,只适用于特定结构的数据。
序列化与反序列化带来双重开销
该方法本质是将对象先转为字符串(JSON.stringify),再解析回对象(JSON.parse)。这涉及两次完整遍历:一次遍历原始数据生成 JSON 字符串,另一次遍历字符串构建新对象。对大型嵌套对象或含大量字段的数组,字符串生成和解析都会显著拖慢执行速度。
- 字符串拼接和内存分配在
stringify阶段开销明显,尤其当属性名或值较长时 -
parse需要语法分析、字符扫描、类型推断,比直接构造对象慢数倍 - V8 等引擎虽对 JSON 操作做了优化,但仍无法绕过文本中间表示带来的固有成本
数据兼容性差,隐性损耗更高
一旦遇到无法被 JSON 表示的值(如 undefined、函数、Symbol、Date、RegExp、Map、Set、循环引用),就会静默丢失或报错。看似“拷贝成功”,实则数据已损坏——这种错误往往延迟暴露,调试成本远超运行时那点性能损耗。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
undefined和函数会被直接忽略(键被删,值变null) -
Date变成字符串,需手动还原;RegExp变成空对象 - 循环引用直接抛
TypeError,无法 fallback
内存占用翻倍,GC 压力增大
中间 JSON 字符串会额外占用内存空间。例如一个 10MB 的纯数据对象,序列化后字符串可能接近相同大小;解析时又新建同等规模的对象结构。短时间内产生大量临时字符串和对象,容易触发频繁垃圾回收,尤其在内存受限环境(如低端移动设备或长时间运行的前端应用)中影响更明显。
- 字符串在 JS 引擎中通常单独分配大块内存,不易复用
- 新对象与原对象无共享,所有嵌套层级都复制,无法按需惰性加载
- 若用于高频操作(如每帧深拷贝状态),极易引发卡顿
替代方案更可控、更高效
真正需要深拷贝时,应按场景选择更合适的手段:
- 简单 POJO 数据 + 兼容性要求低 → 使用结构化克隆(
structuredClone,现代浏览器支持) - 需兼容旧环境 → 选用轻量库如
lodash.cloneDeep(可处理函数、日期等,且支持自定义克隆逻辑) - 高频小对象 → 手动浅拷贝 + 关键字段深拷贝,避免全量递归
- 状态管理场景 → 考虑不可变数据模式(如 Immer),仅代理变更部分,避免无谓复制
不推荐把它当作深拷贝的默认解法。它快在写起来快,而不是跑起来快;省事在代码短,而不是行为稳。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










