扩展运算符只复制对象自身且 enumerable 为 true 的属性,跳过不可枚举属性和继承属性;常见于 Object.prototype 方法、Object.defineProperty 显式设置、类中 getter/setter 等场景。

对象的 enumerable 属性控制它是否能被遍历,而扩展运算符(...)只处理可枚举(enumerable: true)的自有属性——不可枚举的属性会被完全忽略。
哪些属性会被扩展运算符跳过?
只有满足以下两个条件的属性才会被复制:
- 是对象自身的属性(不是继承自原型链)
-
enumerable设置为true
例如:
let obj = Object.defineProperties({}, {val: { value: 1, enumerable: true },
hidden: { value: 99, enumerable: false }
});
let { val, hidden, ...rest } = obj;
console.log(val); // 1
console.log(hidden); // undefined
console.log(rest); // { }
不可枚举属性常见于哪些场景?
很多内置方法或手动定义的对象属性默认不可枚举:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Object.prototype.toString等原型方法 - 通过
Object.defineProperty显式设为enumerable: false的属性 - 类中定义的 getter/setter(若未显式设为
enumerable: true)
这些都不会出现在 {...obj} 或解构赋值的剩余部分中。
扩展运算符不读取原型链上的属性
即使原型上有个 enumerable: true 的属性,扩展运算符也不会复制它:
const child = Object.create(parent);
child.y = 2;
const copied = { ...child };
console.log(copied); // { y: 2 }
console.log('x' in copied); // false
这和 for...in 不同:for...in 会遍历可枚举的继承属性,但扩展运算符只看自身、可枚举、非继承的属性。
如何让不可枚举属性“参与”扩展?
没有直接语法支持,但可通过间接方式暴露:
- 用
Object.getOwnPropertyDescriptors(obj)获取所有属性描述符(含不可枚举) - 过滤出需要的属性,再用
Object.defineProperties({}, descriptors)构建新对象 - 或手动提取:比如
{ ...obj, hidden: obj.hidden }(前提是知道属性名)
注意:这种方式失去“自动收集剩余属性”的便利性,需明确指定。

















