玩转 Object.entries + reduce:从数据转换到函数式编程的思维跃迁

24 阅读4分钟

你是否经常处理对象和数组的嵌套数据?写了一堆嵌套循环、变量名重复、逻辑难懂?在 JavaScript 中,有两个方法看起来简单,组合起来却能解决 80% 的对象结构转换问题,它们就是:

Object.entries + Array.prototype.reduce

无论你是想从后台 API 拿到数据后整理格式,还是要渲染复杂的表格,只要处理的是“对象 + 数组”的嵌套结构,这两个方法就是你最好的朋友。

🧩 Object.entries:让对象也能玩数组操作

你平时用 for...in 遍历对象:

const user = { name: 'Alice', age: 30 };
for (let key in user) {
  console.log(key, user[key]);
}

其实用 Object.entries 你可以写得更简洁:

Object.entries(user).forEach(([key, value]) => {
  console.log(key, value);
});

✅ 它做了什么?

把对象变成了“键值对数组”:

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

console.log(Object.entries(obj));
// 输出: [['a', 1], ['b', 2]]

这样你就可以用数组的方式处理对象了,比如 mapreducefilter 都可以用上!

reduce:最通用的结构转换工具之一

reduce 是数组中最强大的方法之一,它的作用是:

把一个数组 “归纳”为一个结果(可以是数字、对象、数组、任何你想要的结构)

🎯 最常见的例子:数组求和

const arr = [1, 2, 3];
const sum = arr.reduce((acc, cur) => acc + cur, 0);
// acc 是累加器,cur 是当前项
console.log(sum); // 6

🧠 reduce 的参数结构

array.reduce((accumulator, currentValue, index, array) => {
  // 每一步的处理逻辑
  return newAccumulator;
}, initialValue);
  • accumulator:累加器(结果容器)
  • currentValue:当前项
  • initialValue:初始值(比如 0 或 {})

📦 组合起来,用 entries + reduce 解决问题

📚 场景:图书分类数据转扁平列表

你有这样一个对象:

const booksByCategory = {
  fiction: [
    { title: '1984' },
    { title: 'Brave New World' }
  ],
  tech: [
    { title: 'Clean Code' },
    { title: 'You Don’t Know JS' }
  ]
};

你希望把它转换成一个数组,每本书都带上它属于哪个分类

[
  { title: '1984', category: 'fiction' },
  { title: 'Brave New World', category: 'fiction' },
  { title: 'Clean Code', category: 'tech' },
  { title: 'You Don’t Know JS', category: 'tech' }
]

🛠 用 entries + reduce 来写:

const result = Object.entries(booksByCategory).reduce((acc, [category, books]) => {
  const newBooks = books.map(book => ({
    ...book,
    category
  }));
  return acc.concat(newBooks);
}, []);

📌 解析:

  1. Object.entries 把对象变成:[['fiction', [...]], ['tech', [...]]]
  2. 每一类 booksmap 加上分类名
  3. reduce 把所有类的书合并到一个数组里

🎨 图示结构(可选配图)

输入对象:
{
  fiction: [A, B],
  tech: [C, D]
}

转换过程:
Object.entries → [['fiction', [A, B]], ['tech', [C, D]]]
每组 map 添加 category
reduce 合并所有数组

输出结果:
[{...A, fiction}, {...B, fiction}, {...C, tech}, {...D, tech}]

🧠 你已经在用函数式编程了

虽然我们没写什么“函数式编程”的术语,但你其实已经在用了:

概念表现在哪
声明式编程一步表达“我要什么结构”
不可变数据没有修改原数据,而是生成新数组
纯函数mapreduce 都是无副作用的转换
可组合每一步操作都可以替换或重用

函数式编程不是玄学,它可以是你写 JS 的“第二语言”。

Object.entries + reduce 是进入函数式编程思维的绝佳切入点:

  • 🧠 不改原数据
  • 🎯 聚焦目标结构
  • 💪 代码更可读、可维护、可测试

✅ 什么时候该用它?

只要你遇到这类问题:

  • 需要把对象转数组(或反过来)
  • 想要遍历对象内部的数据并做处理
  • 想要结构清晰、逻辑集中

就大胆用 Object.entries + reduce 吧!

📘 什么是函数式编程(Functional Programming)?

函数式编程(Functional Programming, 简称 FP)并不是让你写成数学公式,而是一种更偏“声明式”的写法风格,强调:

  • 纯函数:不修改外部变量,每次调用结果相同
  • 不可变数据:不改变原始输入,而是生成新值
  • 函数组合:将多个小函数组合成复杂逻辑
  • 声明式写法:描述“做什么”,而不是“怎么做”

🔁 函数式 vs 命令式:写法上的哲学分歧

你可以这样理解这两者的对比:

项目函数式编程命令式编程
编程风格声明式:“做什么”命令式:“怎么做”
示例操作map, reduce, filterfor, if, let...
数据处理返回新值(不可变)直接修改变量(可变)
函数特性纯函数,组合函数过程函数,带副作用
举例[].map(fn)for (let i = 0; i < arr.length; i++) {}

🧱 别的编程范式了解下

除了函数式命令式,常见的还有:

编程范式简介
面向对象编程(OOP)以对象为核心,封装状态与行为(如 Java、C++、TS)
事件驱动编程(EDP)常见于前端 UI 和 Node.js(如监听事件、回调)
响应式编程(Reactive)数据变化自动驱动 UI(Vue、React 就是响应式思想)
声明式编程(Declarative)只告诉系统“要什么”,不写具体步骤(SQL、HTML、React 组件)

🧠 最后总结

Object.entries + reduce 是 JS 数据处理的黄金组合。
学会它,你可以少写很多嵌套循环,多写一些优雅、好维护的结构转换代码。

希望你读完后,能在下一次处理数据结构时,自然地想到:

Object.entries + reduce

这不是技巧,是一种写代码的思维方式。

👇 如果你觉得这篇文章有启发,欢迎点赞、收藏,或者评论区聊聊你的理解,一起把代码写得更优雅、更聪明。