标准答案

  1. JSON.stringify 会把 JavaScript 值转换成 JSON 字符串,但 JSON 只能表达有限的数据类型:对象、数组、字符串、数字、布尔值和 null。
  2. undefined、function、symbol 在对象属性中会被忽略,在数组中会变成 null;Date 通常会变成字符串;RegExp、Map、Set 通常会变成空对象;BigInt 会直接抛错;循环引用也会抛错。
  3. JSON.parse(JSON.stringify(obj)) 只能用于简单 JSON 数据的深拷贝。它会丢类型、丢原型、丢不可枚举属性、丢 Symbol 键,也无法处理循环引用。
  4. 需要复制更复杂的数据时,可以优先考虑 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 对象。

作者信息