JavaScript对象浅拷贝默认不处理原型链属性,Object.assign和展开运算符仅复制自有可枚举属性;要保留原型链需先用Object.create(Object.getPrototypeOf(obj))创建新对象,再复制自有属性。

JavaScript 中对象浅拷贝默认不处理原型链上的属性。
Object.assign 和展开运算符不继承原型属性
它们只遍历并复制对象自身的可枚举自有属性(own enumerable properties),完全忽略原型链上定义的属性。
- Object.assign({}, obj):目标对象 {} 的原型是 Object.prototype,不会把 obj.__proto__ 上的属性复制过去
- {...obj}:同理,新对象只拥有 obj 自身属性,原型链关系被切断
- 例如:obj 有一个方法定义在原型上(如 toString 或自定义的 sayHello),浅拷贝后新对象无法调用该方法
想保留原型链,得手动设置新对象的原型
如果需要新对象既拥有原对象的自有属性,又继承其原型行为,不能靠 Object.assign 或展开运算符直接实现,而要分两步:
- 先用 Object.create(Object.getPrototypeOf(obj)) 创建一个继承相同原型的新空对象
- 再用 Object.assign() 或循环赋值,把 obj 的自有属性复制到这个新对象上
- 代码示例:
const shallowCopy = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
注意 accessor 属性和可配置性
如果原对象自身有 getter/setter,且 configurable: false,复制时仍能成功定义到新对象(因为新对象尚未拥有该属性);但之后无法 delete 或重新 define。原型上的 accessor 会自然继承,无需额外操作——前提是没被自有属性遮蔽。
立即学习“Java免费学习笔记(深入)”;
其他方式不推荐用于保留原型
像 JSON.parse(JSON.stringify(obj)) 或 structuredClone 都只处理数据属性,完全丢失原型信息和函数、Symbol、getter/setter 等非数据特性。


















