json深拷贝忽略undefined和symbol是严格遵循规范的必然结果:undefined因json标准不支持而被跳过,symbol因键非字符串且不可枚举而彻底隐身;需改用reflect.ownkeys递归克隆或structuredclone等方案。

JSON 深拷贝(即 JSON.parse(JSON.stringify(obj)))忽略 undefined 和 Symbol 属性,不是实现有误,而是严格遵循 JSON 规范与 JavaScript 引擎行为的必然结果。
undefined 被跳过,因为 JSON 标准不支持它
JSON 规范(RFC 8259 / ECMA-404)只定义六种合法类型:字符串、数字、布尔值、null、数组、对象。它**明确排除 undefined**——既不能作为值,也不能作为键名。
- 在对象中:
{ a: undefined }的a属性会被整个忽略,不进入序列化流程 - 在数组中:
[1, undefined, 3]会变成[1, null, 3](这是唯一“降级”场景) - 顶层值为
undefined时:JSON.stringify(undefined)返回undefined,紧接着JSON.parse(undefined)直接报错
Symbol 属性彻底隐身,连“被过滤”的机会都没有
Symbol 键和值在 JSON.stringify 中是“零存在感”,原因有两层硬限制:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
语法层面不合法:JSON 要求所有键必须是字符串,而
Symbol是 JS 独有原始类型,无法转成合法 JSON 键 -
遍历阶段就被跳过:引擎内部使用类似
Object.keys()或for...in遍历属性,而Symbol属性默认不可枚举;即使设为可枚举,也因非字符串键被直接拒之门外 -
值位置也不保留:如
{ x: Symbol('id') },stringify对该值做类型检查后直接返回undefined,进而导致整条键值对被剔除
这不是 bug,而是设计边界清晰的体现
JSON.stringify 的目标从来不是“完整复制 JS 对象”,而是生成符合 JSON 标准的文本。它不负责保真、不处理语义歧义、不尝试降级转换。
- 它把
undefined当作“无意义字段”直接省略,而非“空值占位” - 它对
Symbol连判断逻辑都不触发——没有 replacer 回调、没有警告、没有 fallback - 这种确定性行为反而让开发者能预判结果,避免隐式错误
想保留它们?得绕开 JSON 流程
若业务需要保留 undefined 或 Symbol,必须放弃 JSON.parse/stringify,改用可控方案:
- 手动递归克隆:用
Reflect.ownKeys()获取全部键(含不可枚举和Symbol),逐个赋值,显式处理undefined - 预处理映射:序列化前将
Symbol键转为带前缀的字符串(如$$sym_id),反序列化后再还原 - 现代替代方案:浏览器可用
structuredClone()(原生支持Symbol、undefined、Date等,但不支持函数和循环引用)










