Object.assign对访问器属性只执行值的浅拷贝,不保留getter/setter;源访问器被转为目标对象的数据属性,其返回值被固化,setter逻辑完全丢失。
Object.assign 在拷贝过程中不会调用源对象上的 getter,也不会在目标对象上保留 setter;它只执行“属性值”的浅拷贝,对访问器属性(accessor properties)的处理是特殊且容易被忽略的。
如果源对象某个属性是通过 get / set 定义的访问器属性,Object.assign 会读取该属性当前的 返回值(即调用 getter),然后把这个值作为普通数据属性赋给目标对象——目标对象上对应键将变成一个可读写的 数据属性,不再具备 getter/setter 行为。
Object.assign 的行为基于 [[Get]] 和 [[Set]] 内部操作,而非 Object.getOwnPropertyDescriptor + Object.defineProperty。因此它不保留属性的 configurable、enumerable、writable 等特性,更不会保留 get / set 函数本身。
for...in 或 Object.keys 遍历到(即 enumerable: true),就会被拷贝Object.getOwnPropertyDescriptors 配合 Object.defineProperties
例如:
立即学习“Java免费学习笔记(深入)”;
const src = { _value: 42, get foo() { return this._value * 2; }, set foo(v) { this._value = v / 2; }};<p>const target = {};Object.assign(target, src);</p><p>console.log(target.foo); // 84(getter 被执行一次,结果被固化)target.foo = 100;console.log(target.foo); // 100(已变成普通数据属性,不再触发 setter)console.log(src._value); // 42(未改变,setter 没生效)
此时 target.foo 是一个纯数据属性,和 src 的访问器逻辑完全脱钩。
若需深拷贝或保留访问器、属性描述符等元信息,应避免直接使用 Object.assign:
Object.getOwnPropertyDescriptors(src) 获取完整属性描述符Object.defineProperties(target, descriptors) 复制过去