一、生活场景:什么叫"数组不扁平"?
想象你收拾衣柜:
- 千层饼数组:[袜子, [裤子, [上衣, 腰带]], 鞋子](找双袜子要翻三层)
- 扁平数组:[袜子, 裤子,上衣,腰带,鞋子](一目了然)
需求:把嵌套数组变成一维数组,就是扁平化!
二、青铜选手: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 编辑过