object.assign只拷贝自身且可枚举的属性,跳过不可枚举属性(如enumerable:false或内置属性)和原型属性;验证是否被拷贝可用hasownproperty(key) && propertyisenumerable(key);拷贝不可枚举属性需用object.getownpropertydescriptors配合object.defineproperties。

Object.assign 只处理“自身 + 可枚举”的属性,不可枚举属性哪怕在对象上真实存在,它也直接跳过。
什么是不可枚举属性
不可枚举属性是指通过 Object.defineProperty 显式设置 enumerable: false 的属性,或者某些内置属性(如 constructor、__proto__)。它们不会出现在 for...in 循环、Object.keys() 或 JSON.stringify() 中。
- 例如:
const obj = {}; Object.defineProperty(obj, 'secret', { value: 42, enumerable: false }); - 此时
obj.secret存在且可读,但Object.keys(obj)返回空数组,Object.assign({}, obj)也不会包含它。
为什么 Object.assign 不拷贝它
它的设计逻辑就是只遍历“可枚举的自有属性”,底层行为等价于对 Object.keys(source) 的结果做赋值。而 Object.keys() 本身就过滤掉不可枚举属性,所以 Object.assign 没有机会接触到它们。
-
Object.getOwnPropertyNames()能拿到所有自有属性名(含不可枚举),但它不是 Object.assign 的遍历依据 - 即使你手动把某个属性设为
enumerable: true,只要它在原型上,依然不会被拷贝——因为还必须满足“自有”这个前提
怎么验证一个属性是否会被拷贝
可以用这个小函数快速判断:
function isCopiedByAssign(obj, key) {<br> return obj.hasOwnProperty(key) && obj.propertyIsEnumerable(key);<br>}
- 返回 true:该属性一定会出现在
Object.assign({}, obj)的结果里 - 返回 false:无论值是什么,都不会被复制(可能是不可枚举、可能是原型属性、也可能两者都不是)
如果真需要拷贝不可枚举属性怎么办
Object.assign 不支持,得换方式:
- 用
Object.getOwnPropertyDescriptors(obj)获取所有自有属性描述符(含不可枚举的),再配合Object.defineProperties(target, descriptors) - 若还需合并多个对象,就得自己写循环,逐个调用
getOwnPropertyDescriptors并处理冲突 - 注意:Symbol 键和访问器属性(getter/setter)同样不会被 Object.assign 处理,也需要额外考虑










