一、生活场景:什么叫"数组不扁平"?
想象你收拾衣柜:
- 千层饼数组:
[袜子, [裤子, [上衣, 腰带]], 鞋子]
(找双袜子要翻三层) - 扁平数组:
[袜子, 裤子,上衣,腰带,鞋子]
(一目了然)
需求:把嵌套数组变成一维数组,就是扁平化!
二、青铜选手:flat()
方法(ES10真香)
const messyCloset = ['袜子', ['裤子', ['上衣', '腰带']], '鞋子'];
const level1 = messyCloset.flat();
const allFlat = messyCloset.flat(Infinity);
我的翻车史:
曾经以为flat(2)
和flat(Infinity)
效果一样,直到遇到五层嵌套数组...
三、白银选手:reduce
+递归(经典永流传)
function flatten(arr) {
return arr.reduce((result, item) => {
return result.concat(
Array.isArray(item) ? flatten(item) : item
);
}, []);
}
const myCloset = ['👖', ['👔', ['🧦']], '👟'];
console.log(flatten(myCloset));
适用场景:
四、黄金选手:toString
妙用(数字数组专属)
const numLayers = [1, [2, [3, [4]]]];
const strFlat = numLayers.toString().split(',');
const numFlat = strFlat.map(Number);
致命缺陷:
- 会把
[1, 'a']
变成['1', 'a']
- 遇到
null, undefined
直接转字符串
五、铂金选手:生成器函数(优雅处理海量数据)
function* flattenGen(arr) {
for (const item of arr) {
Array.isArray(item) ? yield* flattenGen(item) : yield item;
}
}
const hugeArray = [1, [2, [3, [4, ...[1000000个项]]]];
const flattened = [...flattenGen(hugeArray)];
性能优势:
处理超大规模数组时,不会一次性占用大量内存
六、钻石选手:栈结构迭代(避免递归爆栈)
function flattenStack(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const next = stack.pop();
Array.isArray(next) ? stack.push(...next) : result.push(next);
}
return result.reverse();
}
const deepArray = [1, [2, [3, [4]]];
console.log(flattenStack(deepArray));
适用场景:
- 嵌套层级极深时(递归可能栈溢出)
- 需要控制遍历顺序时
七、王者选手:Array.prototype.flatMap
(ES2019)
const data = [1, [2], 3];
const processed = data.flatMap(item =>
Array.isArray(item) ? item : [item * 2]
);
神技巧:
用flatMap
实现过滤+展开二合一:
const mixed = [1, 2, , , 5];
const compact = mixed.flatMap(x => x || []);
八、终极选择指南
场景 | 推荐方案 | 原因 |
---|
现代浏览器环境 | flat(Infinity) | 原生API性能最佳 |
需要兼容IE | reduce +递归 | 兼容性好 |
纯数字数组 | toString +split | 取巧但高效 |
超大数据量 | 生成器函数 | 内存友好 |
需要控制遍历顺序 | 栈结构迭代 | 避免递归爆栈 |
需要边处理边展开 | flatMap | 代码最简洁 |
九、真实案例:树形菜单扁平化
const menuTree = [
{
name: '文件',
children: [
{ name: '新建' },
{ name: '打开', children: [{ name: '从云端' }] }
]
}
];
function getAllNames(items) {
return items.flatMap(item => [
item.name,
...(item.children ? getAllNames(item.children) : [])
]);
}
console.log(getAllNames(menuTree));
转自https://juejin.cn/post/7511969803557584937
该文章在 2025/6/5 11:03:14 编辑过