要确保symbol属性被正确拷贝,必须使用object.getownpropertysymbols()或reflect.ownkeys()获取symbol键,再通过object.defineproperty或直接赋值复制,且symbol值需原样引用不可重建。

要确保 Symbol 属性被正确拷贝,关键在于不能依赖 for...in、Object.keys() 或 JSON.stringify() 这类只处理字符串键的方法——它们根本看不到 Symbol 键。
用 Object.getOwnPropertySymbols() 获取 Symbol 键
这是最基础也最必要的一步。Symbol 键属于对象的“自有属性”,但不可枚举,必须显式提取:
-
Object.getOwnPropertySymbols(obj)返回一个包含所有自有 Symbol 键的数组 - 配合
Object.getOwnPropertyDescriptors(obj)可同时获取 Symbol 键对应的属性描述符(比如是否可写、是否可配置等) - 注意:它不返回继承来的 Symbol 属性,只返回对象自身定义的
遍历并逐个复制 Symbol 属性
拿到 Symbol 键数组后,需手动赋值或定义到新对象上:
- 若只需浅拷贝 Symbol 值(如
Symbol('id')),直接用clone[sym] = original[sym] - 若需保留属性特性(如
enumerable: false或configurable: false),要用Object.defineProperty(clone, sym, descriptor) - 深拷贝时,对
original[sym]的值做类型判断:如果是对象或数组,递归拷贝;否则直接赋值
与字符串键统一处理,避免遗漏
理想做法是把字符串键和 Symbol 键合并处理:
- 用
Reflect.ownKeys(obj)—— 它同时返回字符串键和 Symbol 键,顺序与定义一致 - 再对每个 key 调用
Object.getOwnPropertyDescriptor(obj, key),统一获取描述符 - 这样既能覆盖非枚举的字符串属性(如通过
defineProperty设置的),也能覆盖 Symbol 属性
注意 Symbol 值本身的拷贝行为
Symbol 是原始值,无法“深拷贝”,但可以安全复用:
-
Symbol('a')和Symbol('a')不相等,所以不能新建同名 Symbol 替代 - 拷贝时应直接引用原 Symbol 实例:
clone[sym] = original[sym],保持语义一致性 - 不要尝试
Symbol(original[sym].description),这会创建新 Symbol,失去唯一性与标识意义











