解构赋值+剩余属性收集不是浅拷贝操作,而是属性提取与新对象构造的组合;rest是浅拷贝结果,仅复制第一层可枚举属性,引用类型仍共享内存。

这种写法 不是浅拷贝,而是解构赋值 + 剩余属性收集,它本身不涉及“拷贝”动作,更不等于浅拷贝。
它干了什么?
执行 const { omit, ...rest } = obj 时:
- JavaScript 引擎从
obj中读取所有自身可枚举属性(不含原型链、Symbol、不可枚举属性) - 把
omit对应的属性值提取出来,赋给变量omit - 把其余所有属性(包括嵌套对象、数组等)原样复制到一个新对象
rest中
这个新对象 rest 是一层新的普通对象,但它的属性值仍是原值——基本类型是值拷贝,引用类型仍是地址拷贝。
为什么看起来像“剔除”?
因为 ...rest 只收集你没显式解构的属性,omit 被单独拎走,不再出现在 rest 里。例如:
const obj = { name: 'Alice', age: 30, profile: { city: 'Beijing' } };
const { age, ...rest } = obj;
// rest → { name: 'Alice', profile: { city: 'Beijing' } }
// age → 30
age 没进 rest,但 profile 作为引用类型,完整保留在 rest 中,且和 obj.profile 指向同一内存地址。
它和浅拷贝的关系
{ ...obj } 和 { ...rest } 都属于浅拷贝的一种表现形式——都创建新对象,只复制第一层属性值。区别在于:
-
{ ...obj }:完整复制第一层所有可枚举属性 -
{ ...rest }:是解构后对剩余属性的自动浅拷贝,本质相同,只是范围被你手动限定
也就是说:rest 是浅拷贝结果,但解构过程本身不是拷贝操作,而是属性提取+构造新对象的组合行为。
注意边界
这种写法无法规避浅拷贝固有缺陷:
- 修改
rest.profile.city会影响obj.profile.city - 不处理
null/undefined:若obj是null,会直接报错 - 跳过不可枚举属性(如
Object.defineProperty(obj, 'hidden', { enumerable: false })) - 忽略 Symbol 键,除非显式展开:
{ [Symbol('id')]: 1, ...rest }











