flatMap() 是 map() 和 flat(1) 的组合,先映射再自动展平一层,支持隐式过滤、字段提取与结构标准化,但仅限单层扁平且为同步操作。

flatMap() 是 map() 和 flat(1) 的组合,它先对每个元素执行映射函数(返回一个数组或值),再将所有结果**自动展开一层**,特别适合在一次遍历中完成“拆解 + 清洗”两类操作。
用 flatMap 替代 map + flat 的冗余写法
传统方式需两步:先 map 生成嵌套结构,再 flat 展平。flatMap 把这两步压缩为原子操作,避免中间数组开销。
- ❌ 不推荐:
arr.map(x => x.items).flat() - ✅ 推荐:
arr.flatMap(x => x.items)
在映射过程中自然过滤无效项
flatMap 对返回值有特殊处理:若映射函数返回空数组 [],它会被展平为“无元素”;返回非数组值(如 undefined、null、数字、字符串)则自动包装成单元素数组。因此可利用 [] 实现隐式过滤。
- 清洗含空值的列表:
['a', '', 'b', null, 'c'].flatMap(x => x ? [x.toUpperCase()] : [])→['A', 'B', 'C'] - 拆解并跳过不符合条件的子项:
users.flatMap(u => u.roles?.filter(r => r.active) || [])
拆解嵌套结构同时转换字段
常见于处理树形数据、分组数据或 API 返回的嵌套响应。flatMap 能一边提取深层字段,一边做格式标准化。
- 从多组标签中提取并去重:
posts.flatMap(p => p.tags || []).filter((t, i, a) => a.indexOf(t) === i) - 扁平化评论树并统一结构:
comments.flatMap(c => [{ id: c.id, text: c.text, level: 0 }, ...c.replies?.map(r => ({ id: r.id, text: r.text, level: 1 })) || []])
注意边界:无法替代深度扁平或异步处理
flatMap 只展开**第一层**,不递归;它同步执行,不能 await。需要深度展平请用递归或 flat(Infinity);涉及异步清洗应改用 Promise.all(...).then(...flatMap) 或循环+await。
- ❌ 错误用法:
[[[1, 2]], [[3]]].flatMap(x => x)→[[1, 2], [3]](只展一层) - ✅ 正确替代:
[[[1, 2]], [[3]]].flat(Infinity)或自定义递归函数











