object.assign 默认只复制对象自身的可枚举属性,不复制原型链上的属性,因其内部基于 object.keys() 遍历自身属性,故天然避开原型链继承属性。

Object.assign 默认只复制对象自身的可枚举属性,不复制原型链上的属性,所以它天然避开原型链继承属性——你不需要额外操作来“避开”,它本来就不拷贝。
为什么 Object.assign 不会复制原型链属性
因为 Object.assign 内部遍历的是目标对象的 own enumerable properties(自身可枚举属性),使用的是类似 for...in 但仅限于自身属性的机制(实际基于 Object.keys() + 属性赋值)。原型链上的属性即使可枚举,也不会被遍历到。
例如:
const parent = { inherited: 'from prototype' };
const child = Object.create(parent);
child.own = 'own property';
console.log(Object.keys(child)); // ['own'] —— 只有自身属性
console.log(Object.assign({}, child)); // { own: 'own property' } —— 没有 inherited
确认是否真有原型属性干扰
有时你以为“复制到了原型属性”,其实是因为:
- 源对象本身是用
Object.create(null)创建的(无原型),但目标对象或中间对象有原型方法被意外调用; - 你用
for...in或in运算符检查属性,它们会遍历原型链,造成误解; - 你把函数、Symbol 属性或不可枚举属性误认为是原型属性(Object.assign 同样不复制不可枚举属性和 Symbol 属性)。
如果真想确保“干净”复制(排除所有非自身属性)
可以显式过滤,增强健壮性:
- 用
Object.getOwnPropertyDescriptors()+Object.defineProperties()复制包括不可枚举属性(但依然不复制原型链); - 手动检查
Object.prototype.hasOwnProperty.call(obj, key)再赋值; - 对关键场景,先用
Object.getOwnPropertyNames()获取全部自身属性名再赋值。
例如安全复制自身所有属性(含不可枚举):
function safeAssign(target, source) {
const descriptors = Object.getOwnPropertyDescriptors(source);
Object.defineProperties(target, descriptors);
return target;
}
注意深拷贝与原型无关
Object.assign 是浅拷贝,它不处理嵌套对象的原型问题,只管顶层属性。嵌套对象内部的原型链不受影响,也不被“复制”——只是引用被拷贝过去。如果你担心子对象的原型行为,那是子对象自身的问题,和 Object.assign 是否跳过原型无关。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











