前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Array.prototype.flat 默认深度 flatMap 区别
JSJavaScript数组与集合

Array.prototype.flat 的默认展平深度是多少?flatMap 与先 map 再 flat 有何不同?

flat 不传参时默认深度为 1,只展平一层嵌套;flatMap 等价于 map 后接深度为 1 的 flat,且回调返回数组能改变结果长度。

前端进阶之旅 · 一题精讲更新于 2026.09.05
JavaScript#数组与集合
先看核心答案读代码示例
理解线索

三个关键事实

  1. 默认深度flat() 的 depth 参数缺省为 1,只处理第一层
  2. 等价关系flatMap(cb) 等于 map(cb).flat(1),深度不可调
  3. 长度可变回调返回空或多元素数组可增删结果元素

需要展平两层以上时必须用 flat(n),flatMap 无法替代。

核心回答

先记住这个答案

Array.prototype.flat 的默认深度是 1,即只把第一层子数组的元素拼接进新数组,更深层的嵌套保持原样;需要更深可传入 2、3 或 Infinity。flatMap(callback) 在语义上相当于 arr.map(callback).flat(1):先对每个元素执行回调,再把返回的数组展平一层。区别在于 flatMap 只遍历一次、不产生 map 的中间数组,且深度固定为 1 不可调整。由于回调可以返回任意长度的数组,包括空数组,flatMap 能同时完成映射与过滤,使结果长度与输入不同,这是普通 map 做不到的。

  • flat 不传参默认只展平一层嵌套
  • flatMap 等价于 map 后接深度 1 的 flat
  • flatMap 返回空数组即可过滤,改变结果长度

flat 的深度参数与 flatMap 的两步语义

flat(depth) 会创建一个新数组,把子数组的元素递归拼接到指定深度为止。depth 缺省值是 1,所以 [1, [2, [3]]].flat() 得到 [1, 2, [3]],第三层数组原样保留。它是复制方法,不修改原数组,只返回包含相同元素的浅拷贝。

flatMap(cb) 内部先对每个元素调用回调,把返回值(通常是数组)收集起来,再执行恰好一层的展平。它只遍历一次原数组,不会像 map(...).flat() 那样先分配一个完整的中间二维数组,因此在长链式处理中少一次分配和一次拷贝,但展平能力被锁死在一层。

默认深度与 flatMap 的长度变化JavaScript
const nested = [1, [2, [3, [4]]]];
console.log(JSON.stringify(nested.flat()));
console.log(JSON.stringify(nested.flat(2)));
console.log(JSON.stringify(nested.flat(Infinity)));
const words = ['a b', '', 'c d e'];
const parts = words.flatMap(s => (s === '' ? [] : s.split(' ')));
console.log(JSON.stringify(parts));
console.log(parts.length, words.length);
查看输出与解释
[1,2,[3,[4]]]
[1,2,3,[4]]
[1,2,3,4]
["a","b","c","d","e"]
5 3

这段代码在任意现代浏览器控制台或 Node.js 中可直接运行。前三次打印展示深度 1、2、Infinity 的差异;后半段用 flatMap 把字符串拆词并丢弃空串,结果长度 5 大于输入长度 3,直观说明长度可变。

接口返回的分组数据需要条件拆平并剔除无效项

假设前端拿到接口返回的订单分组:[[{id:1}], [], [{id:2}, {id:3}]],要求交给表格组件的是一层订单数组且丢弃空分组。由于嵌套只有一层,groups.flat() 即可;但若同时要做映射,例如把每组转换为 {id, label} 列表并跳过空组,flatMap 一趟就能完成,避免先 map 再 flat 的两趟遍历。

选择 flatMap 的决策依据是:映射和展平在同一趟循环里完成,中间不产生存放分组数组的临时数组,数据量大时减少内存分配;同时回调对空分组返回 [],展平后该组自然消失,无需再写 filter。最终得到 [{id:1,label:...}, {id:2,...}, {id:3,...}],长度由回调返回值决定。

分组数据映射并剔除空组JavaScript
const groups = [
  [{ id: 1, name: 'A' }],
  [],
  [{ id: 2, name: 'B' }, { id: 3, name: 'C' }]
];
const rows = groups.flatMap(g =>
  g.map(o => ({ id: o.id, label: '#' + o.id + ' ' + o.name }))
);
console.log(JSON.stringify(rows));
console.log(rows.length);
查看输出与解释
[{"id":1,"label":"#1 A"},{"id":2,"label":"#2 B"},{"id":3,"label":"#3 C"}]
3

代码可直接在浏览器或 Node.js 运行。flatMap 的回调把每组映射为行对象数组,空组映射为空数组并在展平时被消除,最终输出 3 行,无需额外的 filter 步骤。

深度超过一层、稀疏数组与泛用性的失效点

flatMap 最常见的失效条件是嵌套超过一层:它固定只展平一层,回调返回 [[1, 2]] 时结果仍是 [[1, 2]],此时必须改写成 map(cb).flat(2) 或 flat(Infinity)。另外若回调返回的不是数组而是单个值,该值会被直接保留,不再展平,容易被误认为发生了递归。

稀疏数组也是边界:flat 会移除展平层级内的空位,[1, , [2, , 3]].flat() 得到 [1, 2, 3],空位被压缩掉,与显式存 undefined 的行为不同。flat 还是泛用方法,可用于有 length 和整数键的类数组对象,但只有真正的数组元素会被展平,类数组子元素原样保留,处理 DOM 集合转换来的数据时要留意。

回答前,多想一步

容易答错的地方

以为 flat() 不传参会展平所有层级
错误。depth 缺省为 1,[1, [2, [3]]].flat() 结果为 [1, 2, [3]],更深层保持嵌套。要完全展平需显式传入足够大的数字或 Infinity,否则深层数据仍是数组。
认为 flatMap 与 map 返回类型必须一致
flatMap 回调可以返回任意长度的数组或单个值:返回 [] 等价于过滤掉该元素,返回多元素数组则扩充结果,因此输出长度可与输入不同;而 map 的输出长度恒等于输入长度。
试着用自己的话回答

面试官还会怎么问?

flat 会修改原数组吗?

不会。flat 是复制方法,返回一个新数组,原数组及其嵌套结构保持不变;但要注意元素是浅拷贝,嵌套对象仍与原数组共享引用。

flatMap 能指定展平深度吗?

不能。flatMap 内部固定只做一层展平,没有深度参数。若映射结果存在两层以上嵌套,只能拆成 map(cb).flat(n) 手动控制深度。

flat 对稀疏数组的空位如何处理?

在展平涉及的层级内空位会被移除,例如 [1, , [2, , 3]].flat() 得到 [1, 2, 3];更深未展平层级中的空位随子数组一起保留,这与显式 undefined 元素被保留的行为不同。

从一道题,走向一组知识

把知识连起来

数组与集合

数组方法 splice 与 slice 在是否修改原数组和参数含义上有何不同?

同属「数组与集合」专题,接着看 splice 与 slice 修改原数组区别 在具体场景中的处理方式。

数组与集合

Map 与普通对象在键的类型上有什么本质不同?为什么需要 Map?

同属「数组与集合」专题,接着看 Map 与普通对象键类型对比 在具体场景中的处理方式。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Array.prototype.flat()

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. flat 的深度参数与 flatMap 的两步语义
  3. 接口返回的分组数据需要条件拆平并剔除无效项
  4. 深度超过一层、稀疏数组与泛用性的失效点
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑