object.assign()只复制对象自身的可枚举属性,忽略原型链上的属性,因其内部使用getownpropertynames+getownpropertysymbols配合propertyisenumerable过滤;保留原型行为应优先用object.create()建立原型链再assign实例属性。

Object.assign() 不会复制原型链上的属性,它只遍历并拷贝对象自身的可枚举属性(即 hasOwnProperty 为 true 的属性),因此原型上的方法或数据属性在合并后会“丢失”。
为什么 Object.assign() 忽略原型属性
这是由其设计机制决定的:
- 它使用 for...in 遍历源对象(但实际内部用的是 getOwnPropertyNames + getOwnPropertySymbols 的组合,再配合 propertyIsEnumerable 过滤);
- 所有原型链上的属性都不满足“自身拥有 + 可枚举”这两个条件;
- 即使原型属性是可枚举的(如通过 Object.prototype.method = function(){} 添加),也不会被复制。
如何保留原型行为?常见解决思路
原型本身不是“数据”,而是对象的行为共享机制。真正需要的往往不是“把原型属性拷进目标对象”,而是让新对象仍能访问原型链。所以更合理的做法是:
-
不依赖 Object.assign() 构造继承关系:用
Object.create(prototype)创建新对象,再用Object.assign()填充自身属性 - 手动复制指定原型方法:仅对关键方法做浅拷贝(需注意 this 绑定和不可枚举性)
-
改用类或构造函数继承:比如用
extends或Object.setPrototypeOf(child, parent.prototype)显式设置原型
一个安全的合并+继承示例
假设你有一个带原型方法的构造函数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function Shape() {}
Shape.prototype.area = function() { return 0; };
<p>const circle = Object.create(Shape.prototype);
circle.radius = 5;
Object.assign(circle, { color: 'red' }); // 只加自身属性</p><p>// ✅ 此时 circle.area() 依然可用,因为原型链 intact
console.log(circle.area()); // 0
console.log(circle.color); // 'red'</p>关键点:先用 Object.create 确保原型链存在,再用 Object.assign 补充实例属性。
如果硬要“把原型属性变成本身属性”
可以借助 Object.getOwnPropertyNames 和 getPrototypeOf 逐层提取,但要注意:
- 会丢失不可枚举属性(除非显式设置
enumerable: true) - 方法会被复制为普通属性,可能破坏
this上下文或装饰器逻辑 - 无法自动处理 getter/setter(需用
Object.getOwnPropertyDescriptor提取描述符再定义)
一般不推荐这种方式,除非明确知道副作用可控。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










