← 返回题目列表

Object.keys、values、entries 和 fromEntries 有什么区别?

中等 第 23 / 28 题 更新于 2026/07/29
ES6Object对象遍历

简化版

Object.keys 返回对象自身可枚举字符串键,Object.values 返回对应值,Object.entries 返回键值对数组;Object.fromEntries 反过来把键值对列表转成对象。

它们都只处理对象自身的可枚举字符串属性,不包含继承属性和 Symbol 属性。常见用途是对象遍历、对象过滤、对象映射,以及和 Map 之间互相转换。

详细版

const user = { id: 1, name: "Ada" };

Object.keys(user); // ["id", "name"]
Object.values(user); // [1, "Ada"]
Object.entries(user); // [["id", 1], ["name", "Ada"]]

fromEntries 可以把键值对还原成对象:

const pairs = [["id", 1], ["name", "Ada"]];
const user = Object.fromEntries(pairs);

过滤对象字段时很常用:

const clean = Object.fromEntries(
  Object.entries(user).filter(([key]) => key !== "password")
);

需要注意,它们不会拿到不可枚举属性、继承属性和 Symbol 键。若要拿全部自有键,通常看 Reflect.ownKeys

完整版教学

一、这组 API 解决什么问题

ES2017 以后,对象遍历不再只能先拿 key 再手动索引取值。keysvaluesentries 分别服务三种视角。

object -> keys    -> key list
object -> values  -> value list
object -> entries -> pair list
pairs  -> fromEntries -> object

这组 API 的核心是把对象转换成数组管道,处理完再转回对象。

二、keys、values、entries 的返回值

const obj = { a: 1, b: 2 };

console.log(Object.keys(obj));
console.log(Object.values(obj));
console.log(Object.entries(obj));
API返回结构适合场景
Object.keys["a", "b"]只关心字段名
Object.values[1, 2]聚合值
Object.entries[["a", 1], ["b", 2]]同时处理键和值

比如统计总分,用 values 足够;字段重命名或过滤,用 entries 更舒服。

三、它们只看自身可枚举字符串属性

const symbolKey = Symbol("id");
const obj = Object.create({ inherited: 1 });

Object.defineProperty(obj, "hidden", {
  value: 2,
  enumerable: false
});

obj.name = "Ada";
obj[symbolKey] = 3;

console.log(Object.keys(obj)); // ["name"]

继承属性、不可枚举属性、Symbol 属性都不会出现。

四、fromEntries 适合对象管道转换

Object.fromEntries 接收可迭代的键值对,不只数组,Map 也可以。

const map = new Map([
  ["theme", "dark"],
  ["pageSize", 20]
]);

const config = Object.fromEntries(map);

对象过滤:

function pick(obj, allowList) {
  return Object.fromEntries(
    Object.entries(obj).filter(([key]) => allowList.includes(key))
  );
}

五、顺序和覆盖规则

对象属性顺序遵循整数索引键、字符串键、Symbol 键的规则;这组 API 只返回字符串键,因此数字样式键会按数字升序提前。

const obj = { b: 1, 2: "two", a: 3, 1: "one" };
console.log(Object.keys(obj)); // ["1", "2", "b", "a"]

fromEntries 遇到重复 key,后面的会覆盖前面的。

Object.fromEntries([["a", 1], ["a", 2]]); // { a: 2 }

六、和 Map 的转换关系

Map 天然就是键值对迭代结构。

const obj = { a: 1 };
const map = new Map(Object.entries(obj));
const back = Object.fromEntries(map);

如果 key 是对象,转成普通对象会被字符串化,不应这样用。

const key = {};
Object.fromEntries([[key, 1]]);
// { "[object Object]": 1 }

七、常见误区与追问

  • 误区:Object.entries 会返回所有属性。 它只返回自身可枚举字符串属性。
  • 误区:Object.values 的顺序完全等于写入顺序。 整数索引键会先按数字升序排列。
  • 误区:fromEntries 能无损转换任意 Map。 对象键会被转成属性键,可能变成字符串。
  • 误区:Symbol 键会出现在 keys 里。 Symbol 键需要 Object.getOwnPropertySymbolsReflect.ownKeys
  • 追问:如何实现对象字段过滤? 可以 entries -> filter -> fromEntries
  • 追问:重复 key 怎么处理? 后出现的键值对覆盖前面的值。

八、加强记忆

记住一个闭环:

Object.entries(obj)
  -> array methods
  -> Object.fromEntries(pairs)

面试回答时先说返回值,再说覆盖范围,最后讲对象过滤、对象映射、Map 转换三个应用。这样能把 API 和真实开发串起来。