json.parse(json.stringify(obj))深拷贝时键名本身不被修改或丢失,但仅保留可序列化的字符串键名,忽略symbol/不可枚举/原型链键及值为function/undefined/symbol的键值对,特殊字符键名会被正确转义还原。

JavaScript 中使用 JSON.parse(JSON.stringify(obj)) 进行深拷贝时,**属性键名本身不会被修改或丢失**,但该方式对键名的“处理”体现在它只保留可被 JSON 序列化的键名,且会忽略不符合 JSON 规范的键值对。
键名必须是字符串(自动转换)
JSON 标准要求对象的键必须是字符串。如果原对象使用 Symbol、数字或布尔值作为键名,JSON.stringify() 会直接忽略这些键(不报错,也不序列化)。
-
Symbol 键会被完全跳过:
{ [Symbol('a')]: 1, b: 2 }→{"b":2} - 数字或布尔键会被转为字符串,但仅限于对象字面量中合法的标识符形式;实际中更常见的是:用数字作键时(如
{ 123: 'x' }),JSON.stringify仍会将其转为字符串"123",这属于合法行为,不是问题
不可枚举属性和原型链上的键名不参与拷贝
JSON.stringify() 只遍历对象自身的、可枚举的字符串键名属性。因此:
- 通过
Object.defineProperty设置的enumerable: false属性会被忽略 - 继承自原型的属性(无论键名是什么)不会被序列化
- 例如:
Object.create({ inherited: 1 }, { own: { value: 2, enumerable: true } })→ 只有{"own":2}
函数、undefined、Symbol 值导致对应键被丢弃
即使键名是合法字符串,若其对应的值为 function、undefined 或 Symbol,整个键值对会在 stringify 阶段被过滤掉(不是键名出错,而是值不可序列化)。
-
{ a: () => {}, b: undefined, c: Symbol('s'), d: 'ok' }→{"d":"ok"} - 注意:键名
"a"、"b"、"c"并未被“处理”,而是整对被剔除
特殊字符键名会被正确转义
包含空格、引号、控制字符等的键名,在 JSON 中会被自动加上双引号并转义,反序列化后还原为原字符串键名,无损。
-
{ "key with space": 1, "a\"b": 2, "\n": 3 }→ 正确序列化与解析,键名保持不变 - 这是 JSON 规范支持的行为,无需额外处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











