javascript 数组扁平化5种实现方法
·
又到年底了。在AI工具的冲击下,普通前端开发者的职场道路似乎更加艰难。
2025年的求职市场早已不是几年前的光景——不再是和面试官简单对答几句就能通过。如今很多面试直接要求手写代码,而且明确规定不能使用AI工具辅助。说实话,我对这种考察方式确实有些抵触。
回归正题,说说今天面试遇到的一道题:数组扁平化。话不多说,直接上代码分析。
方法1:递归forEach版 ✅
const flat = (arr) => {
let newArr = []
arr.forEach((item) => {
if (Array.isArray(item)) {
newArr = newArr.concat(flat(item))
} else {
newArr.push(item)
}
})
return newArr
}
优点:
-
逻辑清晰,易于理解
-
递归思想体现明确
-
使用forEach避免手动索引
缺点:
-
频繁使用
concat创建新数组,性能较差 -
每次递归都创建新的
newArr数组
方法2:reduce递归版 ✅
const flat2 = (arr) => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flat2(cur) : cur)
}, [])
}
优点:
-
代码简洁优雅
-
reduce天然适合累积操作
-
函数式编程风格
缺点:
-
同样存在
concat的性能问题 -
对于不熟悉reduce的开发者可读性稍差
-
每次迭代都创建新数组
方法3:迭代拍平版
const flat3 = (arr) => {
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
优点:
-
迭代而非递归,避免栈溢出风险
-
思路直观:不断展开直到没有嵌套
缺点:
-
每次循环都检查整个数组(
some方法) -
多次创建中间数组,性能最差
-
会修改原数组引用(
arr = [].concat(...arr))
方法4:原生flat版 🏆
const flat4 = (arr) => {
return arr.flat(Infinity)
}
优点:
-
浏览器原生实现,性能最佳
-
语义清晰,维护成本低
缺点:
-
兼容性问题(IE不支持)
-
无法控制扁平化深度以外的逻辑
-
面试中不被允许使用(考察手写能力)
方法5:for...of递归版
function flat5(arr) {
let res = []
for(let item of arr) {
if(Array.isArray(item)) {
res = res.concat(flat5(item))
} else {
res.push(item)
}
}
return res
}
优点:
-
使用for...of语法现代简洁
-
不会改变原始数组,返回新数组
缺点:
-
对于非常大的嵌套数组,递归可能导致栈溢出
-
只能扁平化数组,其他可迭代对象(如 Set、Map)不会被扁平化
性能对比总结
| 方法 | 时间复杂度 | 空间复杂度 | 可读性 | 适用场景 |
|---|---|---|---|---|
| 方法1 | O(n) | O(n) | 好 | 通用递归实现 |
| 方法2 | O(n) | O(n) | 中 | 函数式偏好 |
| 方法3 | O(n×k) | O(n) | 中 | 避免递归栈溢出 |
| 方法4 | O(n) | O(n) | 优 | 生产环境首选 |
| 方法5 | O(1) | O(1) | 差 | 不推荐 |
建议
-
面试准备:掌握方法1或2的递归实现
-
实际开发:优先使用
arr.flat(Infinity)
更多推荐



所有评论(0)