Object.fromEntries 不受属性可枚举性影响,它仅依据输入的可迭代键值对列表构造对象,不读取源对象属性,也不检查enumerable标志;例如手动传入不可枚举属性的键值对仍会被纳入结果。

Object.fromEntries 不受属性可枚举性(enumerable)影响。
它只关心输入的可迭代结构(如数组、Map 或其他实现了 Symbol.iterator 的对象),逐个取出 [key, value] 对,然后直接构造新对象。整个过程完全绕过对象自身的属性枚举机制——既不读取源对象的自有属性,也不检查这些属性是否可枚举、是否在原型上、是否被 Object.defineProperty 设为 enumerable: false。
换句话说:
-
Object.fromEntries的输入不是“一个普通对象”,而是一个键值对列表; - 它不调用
Object.keys()、for...in或Object.entries(),因此根本不会触发枚举性判断; - 即使你手动构造一个包含不可枚举属性的数组传给它,它照样照单全收。
比如:
立即学习“Java免费学习笔记(深入)”;
const data = [
['a', 1],
['b', 2],
[Symbol('c'), 'symbol-key']
];
const obj = Object.fromEntries(data);
console.log(obj); // { a: 1, b: 2 }
// Symbol 键不会出现在普通对象中(除非显式使用 Symbol 作为属性名并保留)再看一个更明确的例子:
const src = {};
Object.defineProperty(src, 'hidden', {
value: 'secret',
enumerable: false,
configurable: true,
writable: true
});
// ❌ 这样不行:Object.entries(src) 返回 [],因为 hidden 不可枚举
console.log(Object.fromEntries(Object.entries(src))); // {}
// ✅ 但你可以手动把它加进去:
console.log(Object.fromEntries([['hidden', src.hidden]])); // { hidden: 'secret' }所以关键点是:
- Object.fromEntries 本身没有“读取对象属性”的行为,它只处理你给它的键值对;
- 如果你先用
Object.entries()提取数据,那才受 enumerable 影响——因为Object.entries()只返回可枚举的自有属性; - 想让不可枚举属性也参与构造,就得绕过
Object.entries(),自己组织键值对数组(例如用Object.getOwnPropertyNames()+ 属性访问,或Object.getOwnPropertyDescriptors()配合Reflect.get())。
常见组合建议:
- 需要完整还原对象(含不可枚举属性)?别用
Object.fromEntries(Object.entries(obj)),改用Object.assign({}, obj)(注意:仍不复制原型方法)或手动遍历Object.getOwnPropertyNames(obj); - 处理 Map?放心用
Object.fromEntries(map),Map 的迭代不受 enumerable 约束; - 从 FormData 或 URLSearchParams 构造对象?它们的
.entries()方法返回的是可迭代键值对,Object.fromEntries能如实转换,与 enumerable 无关。
不复杂但容易忽略。


















