原型属性默认不参与深拷贝,因为深拷贝仅递归复制对象自身的可枚举属性,而原型属性属于继承关系,非实例状态;是否复制取决于场景——纯数据对象可忽略,需保留方法时应显式设置原型。

JavaScript 中手动实现深拷贝时,原型属性默认不会被复制,因为深拷贝操作只处理对象自身的可枚举属性(通过 Object.keys() 或 for...in 配合 hasOwnProperty),而原型链上的属性属于继承而来,并非实例自有。
为什么原型属性不参与深拷贝
深拷贝的本质是创建一个与原对象“结构相同、值独立”的新对象。它关注的是数据内容的递归复制,而非对象的构造关系或行为继承。原型上的方法或属性属于共享逻辑,不属于实例状态的一部分。例如:
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() { return 'Hi'; };
const a = new Person('Alice');
const b = deepClone(a); // 即使实现完美,b 通常也没有 sayHi 方法
此时 b.sayHi 为 undefined,除非显式处理原型。
是否需要复制原型:取决于使用场景
多数业务场景下不需要复制原型——深拷贝用于隔离数据,而非重建类实例行为。但若需保持完整的实例类型和方法可用性,则要考虑原型继承关系:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 纯数据对象(如 JSON-like):忽略原型,安全且高效
- 类实例需保留方法调用能力:应让拷贝对象继承原对象的原型
-
需要完全隔离(包括不可枚举/符号属性):需额外遍历
Object.getOwnPropertyNames和Object.getOwnPropertySymbols,但仍不自动处理原型
手动保留原型的常用做法
在递归克隆函数或对象时,可通过 Object.setPrototypeOf() 显式设置新对象的原型:
- 获取原对象原型:
Object.getPrototypeOf(obj) - 创建空对象并设置原型:
Object.setPrototypeOf(Object.create(null), proto)或更稳妥地用Object.create(proto) - 再将自身属性逐个深拷贝到该对象上
注意:Object.create(null) 创建无原型的对象,不能直接用于继承;应优先用 Object.create(Object.getPrototypeOf(obj))。
更健壮的实现建议
若需兼顾类型、原型、不可枚举属性和循环引用,推荐分层处理:
- 先判断是否为
null、基本类型、函数、日期、正则等特殊对象,分别处理 - 对普通对象或数组,用
Array.isArray()区分,再用Object.getPrototypeOf()获取原型 - 使用 WeakMap 缓存已克隆对象,解决循环引用问题
- 最后用
Object.setPrototypeOf(newObj, proto)恢复原型链
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










