reflect.ownkeys 能获取对象所有自身属性键(含不可枚举属性和 symbol 键),配合 object.getownpropertydescriptor 和 object.defineproperty 可实现保留属性配置的完整浅拷贝,但仍是浅层复制,不处理嵌套引用。

Reflect.ownKeys 本身不执行拷贝,但它可以配合 for...of 或 reduce 等方法,遍历对象自身可枚举和不可枚举的属性(包括 Symbol),从而实现更完整的浅拷贝——比 Object.keys() 或展开运算符更全面。
为什么用 Reflect.ownKeys 做浅拷贝?
它能拿到对象**所有自身属性键**(含不可枚举属性、Symbol 类型键),而 Object.keys() 只返回可枚举字符串键,Object.getOwnPropertyNames() 能拿到不可枚举字符串键但漏掉 Symbol,for...in 还会遍历原型链。所以需要完整覆盖自身属性时,Reflect.ownKeys() 是最全的基础。
基础浅拷贝写法(不含 Symbol 处理)
适用于普通对象,保留不可枚举字符串属性:
- 用
Reflect.ownKeys(obj)获取所有自身键 - 对每个键,用
Object.getOwnPropertyDescriptor(obj, key)拿到属性描述符(含enumerable、writable、configurable和value) - 用
Object.defineProperty()把属性(含配置)复制到新对象上
示例:
function shallowCopy(obj) {
const target = {};
Reflect.ownKeys(obj).forEach(key => {
const desc = Object.getOwnPropertyDescriptor(obj, key);
Object.defineProperty(target, key, desc);
});
return target;
}
const source = { a: 1 };
Object.defineProperty(source, 'b', {
value: 2,
enumerable: false
});
const copy = shallowCopy(source);
console.log(copy.a); // 1
console.log(copy.b); // 2(不可枚举属性也被复制)
处理 Symbol 键的浅拷贝
Reflect.ownKeys() 自动包含 Symbol 键,所以上面的写法默认就支持 Symbol —— 不需要额外判断:
- 如果原对象有
Symbol('x')属性,Reflect.ownKeys()会把它列入键数组 -
Object.getOwnPropertyDescriptor()也能正确读取 Symbol 属性的描述符 -
Object.defineProperty()同样支持用 Symbol 作键设置属性
因此上面的 shallowCopy 函数天然兼容 Symbol,无需修改。
注意:仍是浅拷贝,不递归
这种拷贝只复制第一层属性值:
- 原始值(string/number/boolean/null/undefined)直接赋值
- 对象、数组、函数等引用类型,复制的是内存地址,不是副本
- 修改嵌套对象的属性,源对象和拷贝对象会互相影响
如需深拷贝,不能只靠 Reflect.ownKeys,得配合递归或使用结构化克隆(structuredClone)等方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











