标准答案
- JSON.stringify 会把 JavaScript 值转换成 JSON 字符串,但 JSON 只能表达有限的数据类型:对象、数组、字符串、数字、布尔值和 null。
- undefined、function、symbol 在对象属性中会被忽略,在数组中会变成 null;Date 通常会变成字符串;RegExp、Map、Set 通常会变成空对象;BigInt 会直接抛错;循环引用也会抛错。
- JSON.parse(JSON.stringify(obj)) 只能用于简单 JSON 数据的深拷贝。它会丢类型、丢原型、丢不可枚举属性、丢 Symbol 键,也无法处理循环引用。
- 需要复制更复杂的数据时,可以优先考虑 structuredClone、明确支持范围的手写深拷贝或成熟库。JSON 序列化更适合数据传输和简单持久化,不适合作为通用对象克隆方案。
题目解析
区分 JSON 数据和 JavaScript 对象图很重要。JSON 是数据交换格式,它不能表达函数、原型链、访问器属性、循环引用和很多内置对象的完整语义。
JSON.stringify 支持 replacer 和 space 参数,对象的 toJSON 方法也会影响最终结果。也就是说,序列化结果不一定是原对象结构的机械展开。
structuredClone 覆盖面比 JSON 方案更广,可以处理循环引用和更多内置类型,但它仍然不能克隆函数、DOM 节点等值。选择克隆方案时要先确认数据范围。
代码示例
下面示例展示 JSON 深拷贝会丢失的几类值,以及循环引用会直接报错。
JavaScript
const source = {
name: 'demo',
createdAt: new Date('2026-07-01T00:00:00Z'),
pattern: /js/g,
value: undefined,
run() {},
map: new Map([['a', 1]])
}
JSON.parse(JSON.stringify(source))
// {
// name: 'demo',
// createdAt: '2026-07-01T00:00:00.000Z',
// pattern: {},
// map: {}
// }
const circular = {}
circular.self = circular
// JSON.stringify(circular) // TypeError: Converting circular structure to JSON常见误区
- 把 JSON 方案当成万能深拷贝。
- 忘记 BigInt 会导致 JSON.stringify 抛错。
- 忽略 Date 被转成字符串后不再是 Date 对象。