JS 对象转数组的常用方法:Object.values 与 entries 详解

作者:木棉

时间:2026-11-03

浏览:574

深入详解 JavaScript 中使用 Object.values 与 Object.entries 将对象转换为数组的实用方法,包含语法解析、执行原理、属性排序机制、常见业务场景与选型对比。

文章目录
在 JavaScript 开发中,普通对象(Plain Object)以键值对的形式组织数据,结构直观且查找高效,但无法直接调用 map、filter、reduce 等数组高阶方法。将对象转换为数组是处理复杂业务逻辑、列表组件渲染以及多维数据统计的通用前提。ES2017(ES8)正式引入了 Object.values() 与 Object.entries(),它们与传统的 Object.keys() 构成了原生标准的对象转数组工具链:Object.values 提取对象的属性值组成一维数组,Object.entries 提取键值对元组组成二维数组。本文将从语法规范、底层遍历规则、高频应用模式到反向重构闭环,系统解析这两个方法的技术细节与工程实践。

一、为什么需要将对象转为数组:转换全景与形态分类

JavaScript 的对象与数组具有不同的设计定位。对象是具名属性的离散映射容器,不具备类似 Array.prototype 提供的顺序流式处理管道。当我们需要对对象数据执行如下操作时,将其转换为数组通常是最高效的解决途径:

  • 使用高阶函数链式变换:使用 .filter() 剔除空属性、使用 .reduce() 累计计算总和、使用 .map() 转换字段形态。
  • 对接 UI 渲染框架:React、Vue 等组件视图通常需要针对列表数组进行渲染(如 v-for 或 array.map(...))。
  • 序列化与传输适配:构造 URL 查询参数字符串(Query String)或向只接受二维数组格式的数据结构(如 Map 构造函数)注入数据。

在原生 JavaScript 中,根据所需的数据维度不同,通常有三种转换形态:只取键名、只取属性值、同时保留键名与属性值。下图清晰展示了这三种转换方式的数据流向与结构差异:

JS 对象转数组的常用方法:Object.values 与 entries 详解
图 1:JavaScript 对象转数组转换拓扑与维度映射图(展示 keys、values、entries 的输出形态)

二、Object.values 详解:纯值列表提取与数据聚合

Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组。其输出形态为一个一维数组,数组中元素的排列顺序与使用 for...in 循环遍历该对象时返回的顺序一致(排除了原型链属性)。

2.1 基本语法与基础用法

语法定义十分简洁:

JavaScriptObject.values 语法
Object.values(obj)

参数 obj 表示目标对象。若传入基本类型(如数字、字符串),运行时会将其自动装箱为对应的包装对象;若传入 null 或 undefined,则会抛出 TypeError。

JavaScript基础数据提取示例
// 示例:基础商品价格配置
const productPrices = {
  apple: 8.5,
  banana: 4.2,
  orange: 6.0
};

const prices = Object.values(productPrices);
console.log(prices);
// 示例输出: [ 8.5, 4.2, 6 ]

2.2 典型场景:数值聚合与统计计算

当业务数据以字典形式存储(如统计报表、各科成绩、各渠道销售额),但下游只关心总值或均值时,Object.values 是最优解。通过配合 Array.prototype.reduce,能够以纯函数的形式在一行内完成聚合,无需手动维护外部累加变量:

JavaScript聚合计算与规则校验
// 示例:各科目考试成绩汇总
const scores = {
  math: 92,
  english: 88,
  chemistry: 95,
  physics: 79
};

// 1. 计算总分
const totalScore = Object.values(scores).reduce((sum, val) => sum + val, 0);

// 2. 计算平均分
const avgScore = totalScore / Object.values(scores).length;

// 3. 校验是否存在不及格单科(低于60分)
const hasFailedSubject = Object.values(scores).some(val => val < 60);

console.log("总分:", totalScore);      // 示例输出: 总分: 354
console.log("平均分:", avgScore);      // 示例输出: 平均分: 88.5
console.log("有无不及格:", hasFailedSubject); // 示例输出: 有无不及格: false
JS 对象转数组的常用方法:Object.values 与 entries 详解
图 2:Object.values 数据提取与链式聚合执行流程(4-Stage Pipeline 步骤图)
注意:属性值的浅拷贝特性

Object.values() 返回的新数组本身是一个独立的 Array 实例,对该数组调用 push 或 sort 不会影响原对象。但若原对象的属性值是引用类型(如子对象或嵌套数组),新数组中保存的仍然是该对象的内存引用。修改引用对象的内部属性会同步反映在原对象上。

三、Object.entries 详解:二维键值对与结构变换

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。其结构为二维数组,内部每一个元素均为一个包含两个项的元组 [key, value],其中 key 始终为字符串(即使原对象的键是数字,也会转为字符串),value 为对应的属性值。

3.1 解构遍历与现代迭代

二维元组结构与 ES6 的数组解构语法(Array Destructuring)天然契合。在循环或高阶函数中,可以直接解构出 [key, value],逻辑表达直观:

JavaScript解构遍历示例
const inventory = {
  pens: 120,
  notebooks: 45,
  erasers: 0
};

// 使用 for...of 结合数组解构遍历
for (const [item, count] of Object.entries(inventory)) {
  console.log(`${item} 当前库存: ${count}`);
}
// 示例输出:
// pens 当前库存: 120
// notebooks 当前库存: 45
// erasers 当前库存: 0

3.2 典型场景:复杂属性过滤与 URL 查询参数组装

在实际项目中,纯粹的键名或纯粹的值往往无法满足筛选需求。例如,在提交 HTTP GET 请求前,需要将查询参数对象中值为 null、undefined 或空字符串的非法字段剔除,并完成 URL 编码:

JavaScriptURL 查询参数拼接与过滤
const queryParams = {
  keyword: "javascript",
  page: 1,
  pageSize: 20,
  filterTag: null,       // 空字段
  sort: "createTime_desc"
};

// 1. 过滤掉 null 与 undefined 字段
const validEntries = Object.entries(queryParams).filter(
  ([key, value]) => value !== null && value !== undefined
);

// 2. 构造 URL 查询参数字符串
const queryString = validEntries
  .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
  .join("&");

console.log(queryString);
// 示例输出: keyword=javascript&page=1&pageSize=20&sort=createTime_desc

// 3. 亦可直接传入原生 URLSearchParams 构造器
const searchParams = new URLSearchParams(validEntries);
console.log(searchParams.toString());
// 示例输出: keyword=javascript&page=1&pageSize=20&sort=createTime_desc

3.3 双向闭环:通过 Object.fromEntries 实现清洗与重构

在 ES2019 中,JavaScript 补充了 Object.fromEntries() 方法。它正是 Object.entries() 的逆操作,能够将二维键值对数组无缝还原为一个普通对象。

这形成了一个强大的对象数据变换工程范式:对象输入 → Object.entries 转换为二维数组 → 数组高级方法处理(filter/map)→ Object.fromEntries 重新组装为纯净对象。

JS 对象转数组的常用方法:Object.values 与 entries 详解
图 3:Object.entries 二维键值拆解与 Object.fromEntries 逆向重构闭环架构图
JavaScript对象数据清洗重构范式
const rawForm = {
  username: "  alice_dev  ",
  email: "ALICE@EXAMPLE.COM",
  age: 26,
  internalToken: "secret_12345", // 需要剔除的私有属性
  tempNote: ""
};

// 闭环处理:剔除内部私有属性并清洗字符串空格
const cleanedObject = Object.fromEntries(
  Object.entries(rawForm)
    .filter(([key]) => !key.startsWith("internal") && !key.startsWith("temp"))
    .map(([key, value]) => [
      key,
      typeof value === "string" ? value.trim().toLowerCase() : value
    ])
);

console.log(cleanedObject);
// 示例输出:
// {
//   username: "alice_dev",
//   email: "alice@example.com",
//   age: 26
// }

四、关键规则与边界条件解析

虽然 Object.values 与 Object.entries 易于上手,但在处理包含特殊键名、继承关系或非对象入参时,必须明确其底层规范边界,以避免难以察觉的隐性错误。

4.1 属性遍历顺序规范(ES2015 内部算法)

ECMAScript 规范明确规定了自身属性键的遍历次序(基于 [[OwnPropertyKeys]] 算法)。Object.values 与 Object.entries 严格遵循该次序:

  1. 整数索引键:所有可以转化为 32 位非负整数的属性名,按照升序数值顺序排列。
  2. 普通字符串键:其余非整数键名,按照添加到对象的实际插入时间顺序排列。
  3. Symbol 键:Object.values 与 Object.entries 会完全忽略所有 Symbol 属性。如果需要获取 Symbol 属性对应的内容,必须使用 Object.getOwnPropertySymbols()。
JavaScript属性顺序与 Symbol 键行为示例
const symKey = Symbol("customId");

const mixedObj = {
  "b": "second string",
  "10": "ten",
  "a": "first string",
  "2": "two",
  [symKey]: "symbol value" // 会被忽略
};

console.log(Object.values(mixedObj));
// 示例输出: [ "two", "ten", "second string", "first string" ]
// 说明: 整数键 "2"、"10" 优先按数值升序输出,随后是插入顺序的 "b"、"a",Symbol 被排除

4.2 原型链继承属性与不可枚举属性

与 for...in 循环不同,Object.values 与 Object.entries 不会遍历原型链上的任何继承属性,省去了调用 hasOwnProperty() 进行过滤的手续。同时,通过 Object.defineProperty 设置为 enumerable: false 的属性也会被直接忽略。

4.3 基础数据类型传参时的自动装箱

若向 Object.values 或 Object.entries 传入非对象参数:

  • 字符串:会被装箱为 String 对象,字符串的字符索引(0, 1, ...)成为键名,字符本身成为值。例如 Object.entries("foo") 返回 [["0", "f"], ["1", "o"], ["2", "o"]]。
  • 数字或布尔值:包装后没有自身可枚举属性,返回空数组 []。
  • null 或 undefined:无法被装箱为对象,直接抛出 TypeError: Cannot convert undefined or null to object。在动态入参场景中,应做好空值保护(如 Object.values(data || {}))。
JS 对象转数组的常用方法:Object.values 与 entries 详解
图 4:JavaScript 对象转数组方法选型决策树与逻辑分支图

五、常用转换方法选型与工程总结

在实际项目编码中,面对不同的数据结构与业务目的,应遵循清晰的选型标准。下表与图示总结了 Object.keys、Object.values、Object.entries 的核心特性与边界规范:

JS 对象转数组的常用方法:Object.values 与 entries 详解
图 5:JavaScript 对象转数组核心方法特性与工程边界对比总结图
方法名称 返回维度与类型 是否包含键名 典型适用业务场景 最佳搭配 API
Object.keys() string[] (一维) 仅键名 校验属性必填项、表单字段名校验、获取属性数量 .includes(), .length
Object.values() any[] (一维) 不包含 数据统计聚合、下拉框渲染、批量布尔状态检查 .reduce(), .some(), .every()
Object.entries() [string, any][] (二维) 完整键值 按条件过滤对象属性、URL 参数拼接、字典结构互转 Object.fromEntries(), new Map()

工程最佳实践准则

  1. 只取所需,避免过度转换:若仅需对数值求和,切勿使用 Object.entries() 再解构取值,使用 Object.values() 无论在内存分配还是代码语义上都更为精简。
  2. 谨防 null/undefined 引发崩溃:在接收外部 API 响应或组件 Props 时,始终采用防御性传参,如 Object.entries(apiResponse ?? {})。
  3. 注意数字键的排序效应:依赖对象属性转换数组后的顺序时,需警惕纯数字字符串键的自动升序规则,确保该顺序符合业务预期。
  4. 善用结构闭环:掌握 Object.entries 与 Object.fromEntries 的组合,是实现非侵入式、纯函数式对象数据清洗(Sanitization)的现代标配方案。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章