浅拷贝(如object.assign、展开运算符)不保留getter,仅复制其返回值为静态数据属性;忽略不可枚举属性和symbol键;正确方式是用object.getownpropertydescriptors配合object.defineproperties原样复制描述符。

浅拷贝不会保留 getter,只会把它的返回值当作普通属性写入新对象——结果是 getter 失效,变成静态值。
Object.assign 和展开运算符会执行 getter
它们不是复制访问器定义,而是调用 getter 函数,取回当前返回值,再以数据属性方式赋给目标对象。比如:
- 原对象
get count() { return this._value; },_value是 42; -
Object.assign({}, obj)得到的是{ count: 42 }; - 这个
count不再是 getter,无法再被赋值,也无法响应内部状态变化。
不可枚举属性和 Symbol 键会被忽略
getter 常依赖私有字段(如 _value 或 Symbol 键)来存状态。但 Object.assign 和 {...obj} 只遍历可枚举自有属性,不处理:
- 通过
Object.defineProperty设置的enumerable: false属性; - Symbol 类型的键(哪怕它是 getter 内部读取的关键状态);
- 原型上的 getter(根本不会被遍历到)。
正确保留 getter 的做法
必须绕过“读值写值”逻辑,直接操作属性描述符:
- 用
Object.getOwnPropertyDescriptors(obj)获取所有自有属性的完整描述符(含get、set、enumerable、configurable等); - 用
Object.defineProperties({}, descriptors)把这些描述符原样应用到空对象上; - 这样新对象的
count仍是 getter,访问和赋值行为与原对象完全一致。
注意深拷贝也不自动支持 getter
常见深拷贝手段(如 JSON.parse(JSON.stringify())、Lodash 的 cloneDeep)默认只处理数据属性,同样会丢失 getter/setter。若对象嵌套了带 getter 的子对象,需手动对每一层调用 Object.defineProperties,或借助 Proxy 遍历 descriptor 实现可控克隆。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











