深拷贝 getter/setter 的关键是重建访问器逻辑并作用于新对象自有属性。需用 object.getownpropertydescriptors 获取完整描述符,重写 getter/setter 使其读写新对象字段,字段须先深拷贝,不复制函数本身或闭包变量。

深拷贝 getter 和 setter 的核心不是“复制方法本身”,而是重建访问器逻辑,使其作用于新对象的自有属性上。原 getter/setter 中的 this 指向原对象,直接赋值会失效;必须重定义,并确保内部读写操作落在新对象自身字段上。
拿到完整描述符是前提
用 Object.getOwnPropertyDescriptors(obj) 获取所有自有属性的元信息,包括 get、set、enumerable、configurable、writable 等。它不遗漏不可枚举属性和 Symbol 键,也不受原型链干扰——这是后续精准重建的基础。
getter 要重写,指向新对象的字段
原 getter 函数体里写的 this.xxx 是对旧对象的引用。拷贝时需新建 getter,让它访问新对象上已深拷贝完成的对应字段:
- 若原 getter 是
get name() { return this._firstName + ' ' + this._lastName; },拷贝后应生成get name() { return this._firstName + ' ' + this._lastName; },其中this._firstName和this._lastName是新对象里独立存在的值 - 不能直接把原函数赋过去,否则
this仍绑定旧对象,读到的是旧数据 - 字段(如
_firstName)本身需先完成深拷贝,再供 getter 使用
setter 同理,写入目标必须是新对象
原 setter 往往包含校验、格式化或副作用逻辑,这些行为需要保留,但作用对象必须切换:
- 原
set email(val) { if (!val.includes('@')) throw 'Invalid'; this._email = val.trim(); } - 拷贝后要新建一个
set email(val) { ...; this._email = clonedVal; },其中clonedVal是经深拷贝后的值(比如嵌套对象需递归处理),且this._email是新对象的自有属性 - 若 setter 内部调用了其他方法或修改了其他字段,那些字段也得是新对象上的副本
不拷贝函数本身,也不试图“克隆”闭包
getter/setter 函数体内的自由变量(如外层闭包中的变量)无法被复制。深拷贝只保证:结构隔离、字段独立、访问逻辑复现。函数引用可保留(因逻辑不变),但绝不允许其 this 指向错误对象:
- 不要用
Object.defineProperty(newObj, key, desc)直接挂载原始desc.get,除非你确认它不依赖this或已做bind - 推荐方式:对每个含
get或set的属性,手动构造新函数,显式访问this.某字段,而该字段已在前面步骤中完成深拷贝 - 如果 getter/setter 依赖外部状态(如模块级变量),那它本就不适合深拷贝场景——这类设计应避免
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











