深拷贝时应通过Object.create(Object.getPrototypeOf(obj))设置新对象原型以继承方法,再用Object.getOwnPropertyDescriptors+Object.defineProperties深拷贝自有属性,并处理循环引用及Date/Map等特殊类型。

深拷贝时保留原型链,关键不是“复制 prototype 上的方法”,而是让新对象的 __proto__ 指向原对象的原型,从而自然继承所有原型方法。JavaScript 中方法本身不存储在实例上,而是通过原型链查找——所以你不需要手动复制方法,只需正确设置新对象的原型即可。
用 Object.create() 创建带原型的新对象
这是最直接的方式:获取原对象的原型,再用它创建一个空对象。
- 用 Object.getPrototypeOf(obj) 安全读取原型(比直接访问
__proto__更规范) - 调用 Object.create(proto) 创建新对象,其内部 [[Prototype]] 指向该 proto
- 之后再把原对象的自有属性(非继承)逐个深拷贝过去
拷贝自有属性时保留描述符细节
仅赋值 obj[key] = value 会丢失 getter/setter、writable、enumerable 等特性。应使用:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- Object.getOwnPropertyDescriptors(obj) 获取所有自有属性的完整描述符
- 对每个描述符中的
value或get/set函数做对应处理(如 value 是对象就递归深拷贝) - 用 Object.defineProperties(newObj, descriptors) 一次性定义
处理循环引用和特殊类型
如果原对象含 Date、Map、RegExp 或存在循环引用,需额外支持:
立即学习“Java免费学习笔记(深入)”;
- 用 WeakMap 缓存已拷贝的对象,避免无限递归
- 对内置类型单独判断:
obj instanceof Date→new Date(obj);obj instanceof Map→new Map(obj)等 - 注意:function 和 undefined 无法被结构化克隆,也不建议深拷贝函数体
为什么不推荐手动“复制方法”
原型上的方法是共享的,拷贝它们既无必要也易出错:
- 方法是普通函数对象,若强行深拷贝,会生成新函数,失去与原构造函数的关联
- 闭包、this 绑定、name 属性等可能被破坏
- 真正需要的是行为一致,而原型继承天然保证这点

















