JSON.stringify() 会丢数据,因其仅序列化可枚举自有属性,并静默忽略 undefined、function、symbol,将 Date 转为 ISO 字符串,NaN/Infinity 变 null,循环引用则报错;JSON.parse() 返回纯数据对象,丢失方法、原型和构造器信息。

JavaScript 对象和 JSON 字符串之间转换,核心就靠 JSON.stringify() 和 JSON.parse(),但直接套用常出问题——比如函数丢失、undefined 被忽略、日期变字符串、循环引用直接报错。
为什么 JSON.stringify() 会丢数据?
它只序列化可枚举的自有属性,且对某些值有硬性过滤规则:
-
undefined、function、symbol类型的属性值会被静默忽略(不是报错,是“看不见”) -
Date对象会被转成 ISO 字符串,比如new Date()→"2024-05-12T08:30:45.123Z" -
NaN和Infinity变成null - 对象含循环引用(比如
a.b = a)时,直接抛TypeError: Converting circular structure to JSON
如果要保留函数或特殊类型,得自己写 replacer 函数,或者换用第三方序列化方案(如 flatted 或 serialize-javascript),但那就不是标准 JSON 了。
JSON.parse() 后得到的不是原对象?
是的。JSON.parse() 只返回纯数据对象(plain object),所有方法、原型链、构造器信息全部丢失:
立即学习“Java免费学习笔记(深入)”;
const obj = { x: 1, method() { return this.x; } };
const json = JSON.stringify(obj); // {"x":1}
const parsed = JSON.parse(json); // { x: 1 } —— method 没了,parsed.constructor 是 Object,不是原来的类
如果需要还原实例(比如 Date、Map、自定义类),必须手动处理:
- 日期字符串可加
reviver参数识别并重建:JSON.parse(json, (k, v) => v instanceof String && /^\d{4}-\d{2}/.test(v) ? new Date(v) : v) -
Map/Set等无法直出,得先转成数组格式再解析后重建 - 自定义类必须在解析后显式调用构造函数或
Object.assign()注入数据
遇到循环引用怎么办?
标准 JSON 不支持循环引用,所以不能硬转。常见应对方式:
- 提前检测并断开引用(比如用
WeakMap记录已遍历对象) - 用
JSON.stringify(obj, (k, v) => (v === obj) ? undefined : v)简单跳过自身引用(治标) - 改用
structuredClone()(现代浏览器)做深拷贝,不走 JSON 中间态;或用flatted.stringify()/parse()支持循环的替代方案 - 服务端接口设计时,避免返回带循环的数据结构(比如 ORM 默认 eager-load 出来的父子关系)
真正难的不是调用那两个函数,而是意识到 JSON 只是数据交换格式,不是 JavaScript 对象的完整快照——哪些能过,哪些会掉,哪些要额外兜底,得看具体字段类型和业务约束。











