object.assign 拷贝时只读取源对象的自有可枚举属性,触发 getter 和 proxy trap,但不访问继承、不可枚举或 setter 属性,且仅执行浅拷贝。

Object.assign 在拷贝过程中,对每个源对象的**自有可枚举属性**执行一次 读取(get)操作,该读取发生在属性被复制到目标对象之前,并且遵循 JavaScript 的属性访问规则(包括 getter、代理 trap 等)。
只读取自有可枚举属性
Object.assign 不会访问继承属性或不可枚举属性。即使源对象上定义了 __proto__、constructor 或 toString 这类原型链上的方法,只要它们不是自有且可枚举的,就不会被读取或拷贝。
- 使用
Object.defineProperty设置enumerable: false的属性会被跳过 - 通过
Object.create创建并挂载在原型上的属性不会触发读取 - Symbol 属性若为可枚举(极少情况),也会被读取;但默认 Symbol 属性不可枚举,故通常不参与拷贝
读取时会触发 getter 和代理 trap
如果源对象某个属性是通过 get 定义的访问器属性,或者源对象是 Proxy,那么 Object.assign 内部会实际调用该 getter 或触发 handler.get,并将返回值赋给目标对象对应属性。
- getter 中的副作用(如 console.log、计数器自增)会在拷贝时发生
- Proxy 的
gettrap 可以拦截并修改返回值,甚至抛出错误导致拷贝中断 - 注意:setter 不会被调用,Object.assign 是“读-写”模式,只读源、只写目标
按源对象顺序依次读取,浅拷贝语义
Object.assign 从左到右遍历参数列表中的每个源对象,对每个源对象内部按 for...in 类似顺序(实际依赖引擎实现,但保证可枚举性)读取属性键值。相同键名后出现的源对象会覆盖前面的值。
- 读取操作是同步且即时的:不会延迟、不会缓存、不会跳过中间计算
- 如果某属性在读取瞬间返回
undefined(比如 getter 返回 undefined),目标对象上该属性就被设为undefined - 数组作为源对象时,索引被视为字符串键(如 "0", "1"),length 等不可枚举属性不参与读取
不处理 getter/setter 结构的完整迁移
Object.assign 只拷贝属性的当前值,而非属性描述符本身。即使源属性是 getter,目标对象上得到的是一个普通数据属性,不再具备响应式行为。
- 无法保留
writable、configurable、enumerable等特性 - 想完整复制属性定义,需用
Object.getOwnPropertyDescriptor+Object.defineProperty - 深拷贝需求应选用结构化克隆、structuredClone 或第三方库,而非依赖 Object.assign 的读取逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











