Object.assign只复制对象自身的可枚举属性,不处理原型链、不可枚举属性、Symbol键、getter/setter及属性描述符;其行为等价于target[key] = source[key],为浅拷贝且同名属性后写入者覆盖前者。

Object.assign 不会复制原型链上的属性,只处理对象自身的可枚举属性。 它本质上是浅拷贝,且仅遍历目标对象的 ownKeys(即自身所有可枚举字符串键和 Symbol 键),完全忽略从原型继承来的属性。
只遍历自身可枚举属性
当调用 Object.assign(target, source) 时,JavaScript 引擎会调用 Reflect.ownKeys(source) 获取 source 对象**自身**的所有键(包括不可枚举的字符串键和 Symbol 键),但随后只对其中**可枚举的属性**执行赋值。原型链上的属性(无论是否可枚举)都不会被访问或复制。
- 例如:若
source继承自某个原型并拥有toString方法,该方法不会被复制到target - 即使在原型上定义了
Object.defineProperty(obj, 'x', { value: 1, enumerable: true }),x仍属于原型属性,Object.assign不会读取它
不触发 getter/setter,也不保留属性描述符
Object.assign 的行为等价于简单的赋值操作 target[key] = source[key],因此:
- 如果 source 的某个属性是 getter,赋值时会**调用 getter 获取返回值**,然后将该值写入 target 的同名属性(作为普通数据属性)
- setter 不会被触发(因为不是通过
set赋值,而是直接写入) - 属性的
writable、configurable、enumerable等特性全部丢失,目标属性总是变成默认可写、可配置、可枚举的数据属性
无法继承原型,但可手动设置原型
Object.assign 本身不修改 __proto__ 或 [[Prototype]]。若希望 target 继承 source 的原型,需额外操作:
立即学习“Java免费学习笔记(深入)”;
- 使用
Object.setPrototypeOf(target, Object.getPrototypeOf(source)) - 或在创建 target 时就指定原型:
Object.assign(Object.create(Object.getPrototypeOf(source)), source) - 注意:直接修改
__proto__不推荐,应优先使用Object.setPrototypeOf()
替代方案:需要深拷贝或保留原型时怎么办
若业务场景要求复制原型链、不可枚举属性或完整属性描述符,Object.assign 不适用,可考虑:
- 用
Object.getOwnPropertyDescriptors(source)+Object.defineProperties(target, descriptors)复制所有自身属性(含不可枚举和描述符) - 结合
Object.getPrototypeOf(source)和Object.setPrototypeOf()显式重建原型关系 - 深拷贝场景建议使用结构化克隆(
structuredClone)或成熟库(如 lodash 的cloneDeep),而非自行递归处理Object.assign


















